퀘스트 JVM : 자바 메모리 영역

노트의이 시리즈는 주로 기반으로 "자바 가상 머신에 대한 심층적 인 이해 : JVM은 고급 기능과 모범 사례 제 2 판"이 책 연구 노트.

개요

이 메모리 누수와 오버 플로우 영역에 이르는 문제가있는 경우 자바 프로그래머가 메모리 관리 작업을 많이 공유 할 가상 머신이 아닌 메모리 누수 및 C / C ++와 같은 경향으로 메모리 오버 플로우 문제, 그것은 이것이다, 그것은 어려울 것이다 조사. 좋은 자바 프로그래머가 자바 가상 머신의 충분한 지식을 가지고 있어야 그래서, JVM은 당신의 필수 코스입니다.

런타임 데이터 영역

에 따르면 "자바 가상 머신 사양 (자바 SE 버전 7),"JVM에 의해 관리 나누어 메모리 영역은 다음과 같이



각각의 메모리 영역은 자신의 용도뿐만 아니라, 시간의 창조와 파괴를 가지고, 일부 지역에 가상 컴퓨터를 시작합니다 어떤 영역이 메모리 영역에 대한 설명은 다음 작성 및 삭제 사용자 스레드에 의존하고있다.

프로그램 카운터

프로그램 카운터 (프로그램 카운터 레지스터)는 인 스레드 전용 메모리 영역, 현재 스레드를 실행 줄 수 바이트 코드 포인터는 작은 메모리 공간입니다.

바이트 코드 인터프리터 작업 (Java 소스 코드 바이트 머신 런타임 실행되도록 해석 코드로 컴파일된다) 때, 실행될 다음의 바이트 코드를 선택하기 위해, 프로그램 카운터의 값을 변경하는 것이다. 지점, 루프, 프로그램 카운터는 모든 실행 따라 이동합니다.

스레드 자바 방법을 실행하면, 프로그램 카운터가 실행되고있는 가상 머신 바이트 코드 명령어의 주소를 기록하고, 실행의 스레드, 프로그램 카운터의 값은 널 (미정의) 인 기본 방법. 프로그램 카운터는 메모리 OutOfMemoryError가 Java 가상 머신 사양의 지정된 영역에 하나이 아니다.

자바 가상 머신 스택

스택 자바 가상 머신 (자바 스택)입니다 스레드 개인 메모리 영역, 수명주기와 동일한 스레드. 자바 메모리 모델 한 방법이 실행 가상 머신 스택은 : 각각의 방법은에서 실행 생성 스택 프레임 (스택 프레임)을 저장하는 로컬 변수 테이블 정보를 오퍼랜드 스택, 동적 링킹, 방법 수출. 스택 프레임의 실행 완료 개시로부터 각각의 메소드 호출 방법은 스택의 스택에 스택에서 가상 머신에 대응한다.

다양한 공지의 기본 데이터 형식 컴파일 저장된 로컬 변수 테이블 (부울 바이트 문자 짧은 긴 이중 플로트 INT), 오브젝트 참조 및 리턴 주소 유형 (바이트 코드 명령의 어드레스를 가리키는). 할당 컴파일 메모리 공간 중에 만들어 필요한 로컬 변수 테이블은 메소드를 입력 할 때하면 스택 프레임에 할당 된 로컬 변수가 완전히 정의에 대해, 상기 방법은 로컬 변수 테이블의 크기의 동작 동안 변화하지 않는 정도의 공간을 필요로한다.

StackOverflowError가와 OutOfMemoryError가 : Java 가상 머신 사양에서, 자바 가상 머신 스택이 개 이상이있을 수 있습니다. 요청 스레드 스택 깊이 StackOverflowError가 가상 머신 스택의 의지 깊이보다 큰 경우. 자격 메모리가 부족 스택은 동적으로는 OutOfMemoryError가이 가상 머신을 것입니다 확장합니다.

네이티브 메소드 스택

Java 가상 머신 스택 효과를 네이티브 메소드 스택 (네이티브 메소드 스택)이며, 스레드 개인 차이가 자바 가상 머신 스택이 기본 방법을하지 않는 Java 메소드 서비스, 기본 방법 서비스에 대한 네이티브 메소드 스택, 가상 머신 사양을 수행 할 수 있다는 것입니다, 스택 결합 된 가상 머신 네이티브 메소드 스택 및 스택에 핫스팟 가상 머신에 필수했다. 이 메모리 영역은 StackOverflowError가와 OutOfMemoryError를 던질 수 있습니다.

Java 힙

Java 힙 (자바 힙)의 모든 조각입니다 공유 스레드 메모리 영역의뿐만 아니라 메모리의 가장 큰 블록을 관리하는 자바 가상 머신은 때 가상 머신이 시작 만들어집니다. 이 메모리 영역의 유일한 목적은 개체 인스턴스를 저장 거의 모든 개체 인스턴스가 메모리를 할당하기 위해 여기에 있습니다.

자바 가비지 컬렉터 힙 관리 힙이라고도 주 영역이다 "GC 힙." 이제 기본적으로 너무 메모리 복구의 관점에서, 세대 수집 알고리즘을 사용하여 가비지 컬렉터는, Java 힙은 또한으로 나눌 수 있습니다 신구 세대의, 공간의 새로운 세대의 에덴으로 세분화 할 수있다, 생존자 공간에서에 생존자 공간 .

아래 그림과 같이 :

메모리 할당의 관점에서, 스레드 (로컬 할당 버퍼, TLAB 스레드) 자바 힙 버퍼를 할당 개인 여러 스레드로 분할 될 수있다 공유 할 수 있습니다. 가상 머신은, 새로운 개체에 대한 메모리를 할당하기 이전에 각 스레드 자바에있는 작은 메모리에 할당 된 힙라는 지역 스레드 할당 버퍼 (TLAB). 그것은 단지 TLAB 밖으로 실행하고 새로운 TLAB를 할당하는 스레드 TLAB에 할당 할 때 메모리를 할당 할 스레드 (동시 경우 스레드 안전을 위해) 잠금을 동기화합니다.

긴 논리적으로 연속 될 수 있습니다 자바 스택은 불연속 물리적 메모리 공간에있을 수있다. 이 힙 할당 된 인스턴스를 완료하기에 충분한 메모리가 아닌, 및 확장 할 수없는 경우 때 OutOfMemoryError가 발생합니다.

방법 지구

구역 방법 (방법 에라)와 Java 힙은 마찬가지로 스레드 공유 가상 머신을 기억하는 기억 영역이로드 된 클래스 정보, 상수, 정적 변수, 타임 컴파일러 코드 컴파일 및 기타 데이터. 가상 머신 사양, 그것은 스택의 논리적 부분으로 설명되어 있지만 실제로는 Java 힙과 구별되어야한다.

从分代收集的角度看,方法区也被称做永久代(Permanent Generation),实际上两者并不等价,只是因为 HotSpot 虚拟机使用永久代实现了方法区,对于其他虚拟机(JRockit、IBM J9)是不存在永久代概念的。

使用永久代实现方法区,更容易出现内存溢出问题(永久代有 -XX:MaxPermSize 的上限),所以在 JDK1.8 中,HotSpot 就取消了永久代(JEP122),取而代之的是元空间(MetaSpace),元空间是方法区新的实现,而且使用的是本地内存不是虚拟机内存。原先永久代中类的元信息会放入元空间,类的静态变量和常量会放入 Java 堆。

永久代也并不是指真的“永久”存在,只是说这部分内存回收(常量池回收和对类型的卸载)的成绩难以令人满意,条件也非常苛刻。

方法区会有 OutOfMemoryError 异常。

运行时常量池

运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本信息、字段、方法、接口等描述信息外,还有一项信息就是常量池,用于存放编译期间生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中,另外翻译出来的直接引用也会存储在这个区域中。

这个区域另外一个特点就是动态性,Java并不要求常量就一定要在编译期间才能产生,运行期间也可以在这个区域放入新的内容,String.intern()方法就是这个特性的应用。此区域有 OutOfMemoryError 异常。

JDK1.6及之前,常量池是位于方法区中的,但在JDK1.7的时候常量池挪到了堆内存,也就是常量池和对象共享 Java 堆,所以在 Java7 以后,常量池就不在方法区分配了,而是在 Java 堆 中分配。

直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域。但这部分区域被频繁的使用,也可能导致 OutOfMemory 异常出现。

JDK1.4 中加入了 NIO,这是一种基于通道(Channel)和缓冲区的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样显著提高了性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。显然,本机直接内存的分配不会受到 Java 堆大小的限制,但是,既然是内存,肯定还是会受到本机总内存(包括RAM、SWAP区)大小以及处理器寻址空间的限制。在配置虚拟机参数时,会根据实际内存配置 -Xmx 等,但经常忽略直接内存,使得各个内存区域总和大于了物理内存,从而导致动态扩展时出现 OutOfMemoryError。

추천

출처www.cnblogs.com/cellei/p/12113354.html