>  기사  >  Java  >  JVM 기본 소개: 런타임 데이터 영역

JVM 기본 소개: 런타임 데이터 영역

巴扎黑
巴扎黑원래의
2017-07-21 16:46:33949검색

이 그림은 JVM을 접한 모든 사람에게 친숙할 것입니다. 이것이 JVM을 시작하기 위한 첫 번째 교훈이라고 할 수 있습니다. 그중에서도 "heap""가상 머신 스택(stack)"이 더욱 친숙합니다. 다음은 이 사진을 바탕으로 ​​JVM의 런타임 데이터 영역에 대해 간략하게 소개하겠습니다.

프로그램 카운터(Program Counter Register)

컴퓨터 운영체제에서 프로그램 카운터는 다음 명령의 주소를 나타냅니다. JVM의 프로그램 카운터의 경우 이는 현재 스레드에서 실행되는 바이트코드의 줄 번호 표시로 볼 수 있습니다. 각 스레드에는 프로그램 카운터가 있습니다. 작업 실행, 스레드 전환 후 올바른 위치로 복원될 수 있는지 확인하려는 경우) 중요한 점——프로그램 카운터는 JVM 사양에서 유일하게 지정하지 않은 것입니다. OutOfMemory(메모리 누수, 이하 OOM 영역이라고 함)이 발생할 수 있습니다. 즉, 위 사진의 나머지 4 영역은 OOM을 유발할 수 있습니다.

☆가상 머신 스택(Java Virtual Machine Stacks)

이 메모리 영역은 우리가 흔히 "stack"이라고 부르는 영역입니다. 변수를 저장하는 데 사용됩니다. 즉, 예를 들면 다음과 같습니다.

int i = 0;

  가상 머신 스택 메모리는 4바이트를 사용하여 i 변수를 저장합니다. 변수의 메모리 공간은 처음부터 결정될 수 있으므로(참조 변수의 경우 물론 주소 참조가 저장되며 크기도 고정되어 있음) 이 메모리 영역은 컴파일러에 의해 결정될 수 있습니다. StackOverflowError 또는 OOM 오류. JVMparameters"-Xss228k"(스택 크기는 228k)을 설정합니다. rreee

 실행 결과는 아래 그림과 같습니다. JVMStackOverflowError를 발생시킵니다. 이는 스레드가 요청한 스택 깊이가 에서 허용하는 깊이보다 크다는 의미입니다. JVM.

 단일 스레드 상황에서는 어쨌든 StackOverflowError이 발생합니다. OOM 예외가 발생하는 경우 메모리가 소진될 때까지 스레드가 계속 생성되기 때문입니다.

 JVM의 메모리는 힙 메모리 + 메소드 영역 메모리 + 남은 메모리, 즉 남은 메모리 =메모리 JVM에 할당된 메모리로 구성됩니다. 운영 체제별 - 힙 메모리 - 메서드 영역 메모리. -Xss는 각 스레드의 스택 용량을 설정합니다. 이는 생성할 수 있는 스레드 수를 의미합니다. = 남은 메모리 / 스택 메모리. 이때, 스택 메모리가 크면 생성 가능한 스레드 수가 적어지고, 스택 메모리가 작으면 생성 가능한 스레드 수가 OOM 발생하기 쉽습니다. 더 커지고 OOM이 쉽게 발생하지 않습니다.

이 상황을 피하는 가장 좋은 방법은 힙 메모리 +메서드 영역 메모리를 줄이거나 스택 메모리를 적절하게 줄이는 것입니다. 스택 메모리 구성은 일반적으로 기본값인 1M을 사용하거나, 64비트 운영체제와 64비트 JVM을 사용합니다.

네이티브 메소드 스택(Native Method Stack)

로컬 메소드 스택은 가상 머신 스택과 유사하지만, 가상 머신 스택은 Java 메소드를 제공한다는 점이 다릅니다. 로컬 메소드 스택이 제공하는 것은 Native 메소드입니다. HotSpot 가상 머신 구현에서는 로컬 메서드 스택과 가상 머신 스택이 하나로 결합됩니다. 마찬가지로 StackOverflowErrorOOM 예외도 발생합니다.

Java 힙

  对于堆,Java程序员都知道对象实例以及数组内存都要在堆上分配。堆不再被线程所独有而是共享的一块区域,它的确是用来存放对象实例,也是垃圾回收GC的主要区域。实际上它还能细分为:新生代(Young Generation)、老年代(Old Generation)。对于新生代又分为Eden空间、From Survivor空间、To Survivor空间。至于为什么这么分,这涉及JVM的垃圾回收机制,在这里不做叙述。堆同样会抛出OOM异常,下面例子设置JVM参数” -Xms20M -Xmx20M(前者表示初始堆大小20M,后者表示最大堆大小20M)。

 1 package com.jvm; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 /** 7  * -Xms20M -Xmx20M 堆初始大小20M 堆最大大小20M 8  * Created by yulinfeng on 7/11/17. 9  */10 public class Test {11 12     public static void main(String[] args) {13         List<Test> list = new ArrayList<Test>();14         int count = 0;15         try {16             while (true) {17                 count++;18                 list.add(new Test());   //不断创建线程19             }20         } catch (Throwable e) {21             System.out.println("创建实例个数:" + count);22             e.printStackTrace();23         }24 25     }26 }

  执行的结果可以清楚地看到堆上的内存空间溢出了。

方法区(Method Area

  对于JVM的方法区,可能听得最多的是另外一个说法——永久代(Permanent Generation),呼应堆的新生代和老年代。方法区和堆的划分是JVM规范的定义,而不同虚拟机有不同实现,对于Hotspot虚拟机来说,将方法区纳入GC管理范围,这样就不必单独管理方法区的内存,所以就有了永久代这么一说。方法区和操作系统进程的正文段(Text Segment)的作用非常类似,它存储的是已被虚拟机加载的类信息、常量(从JDK7开始已经移至堆内存中)、静态变量等数据。现设置JVM参数为-XX:MaxPermSize=20M(方法区最大内存为20M)。

 1 package com.jvm; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 /** 7  * -XX:MaxPermSize=20M 方法区最大大小20M 8  * Created by yulinfeng on 7/11/17. 9  */10 public class Test {11 12     public static void main(String[] args) {13         List<String> list = new ArrayList<String>();14         int i = 0;15         while (true) {16             list.add(String.valueOf(i++).intern());   //不断创建线程17         }18     }19 }

 실제로 위 코드의 경우 JDK6, JDK7, JDK8에서 실행 결과가 다릅니다. 그 이유는 문자열 상수 풀이 여전히 JDK6의 메서드 영역(영구 생성)에 저장되어 있기 때문에 OutOfMemoryError:Permanent Space이 발생하고 JDK7 뒤에 문자열 상수가 발생하기 때문입니다. will throw됩니다. 풀이 Java 힙으로 이동되었습니다. 위 코드는 OOM을 발생시키지 않습니다. 힙 메모리가 20M로 변경되면 OutOfMemoryError:Java가 발생합니다. heap space; JDK8에서는 단순히 메소드 영역의 개념을 취소하고 "metaspace(Metaspace)"로 대체했습니다. 가상 머신 매개변수 "-XX:MaxPermSize"는 의미가 없으며 대체 매개변수는 "-XX:MetaspaceSize""-XX:MaxMetaspaceSize"etc입니다.

위 내용은 JVM 기본 소개: 런타임 데이터 영역의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.