1. 프로그램 카운터: 스레드 프라이빗, 현재 실행된 명령어의 위치를 저장하는 데 사용됨
2. 자바 가상 머신 스택: 스레드 Private은 Java 메서드 실행 모델을 설명합니다. 메서드를 실행할 때 로컬 변수, 기본 유형 변수, 참조 및 기타 정보를 저장하기 위해 스택 프레임이 생성됩니다.
3. Java 기본 메서드 스택: 스레드 전용, 다음에서 사용하는 기본 메서드 제공 가상 머신
4. Java 힙: 스레드에 의해 공유되며 가비지 수집기의 주요 작업 장소이며 객체 인스턴스 등을 저장합니다.
5. 메서드 영역: 스레드에 의해 공유되는 클래스 정보, 상수, 정적 변수,
런타임 상수: 컴파일을 위해 저장됨
할 때 생성된 다양한 리터럴 및 기호 참조 6. 직접 메모리: 머신 메모리
먼저 상수 풀이 있는지 확인하세요. 해당 기호 참조를 찾을 수 있으며 클래스가 로드 및 초기화되었는지 확인할 수 있습니다. 그렇지 않으면 로드 프로세스를 먼저 수행해야 합니다.
객체에 대한 메모리 할당: 공간을 계산하고 힙에서 연속 또는 불연속 영역을 나눕니다. 스레드 안전 문제를 방지하려면 cas+failure 재시도를 사용하세요(객체가 매우 자주 생성되기 때문에 현재 메모리가 할당되었는지 알 수 없음)
메모리 공간 초기화: 할당된 메모리 공간을 0 값으로 초기화
객체의 기본 정보 설정: 메타데이터, 해시 코드, gc 등
java init 초기화 실행:
객체 헤더: 객체의 해시 코드 저장, 잠금 상태 등을 입력하고 포인터(객체가 가리키는 클래스의 메타데이터)
인스턴스 데이터: 객체가 실제로 저장한 정보
정렬 채우기: 규칙을 준수하여 채우기
객체 액세스는 Java 스택의 참조 데이터를 통해 객체에 대한 참조를 유지합니다
액세스 방법: 핸들 및 직접 액세스
에 의해 힙에서 핸들 풀을 유지하는 경우 참조는 다음을 가리킵니다. 핸들, 핸들에는 객체 인스턴스 데이터 및 유형 데이터의 주소 정보가 포함될 수 있습니다.
/ Direct: 객체 주소를 직접 가리키는 참조 3, 실제 전투 OutofMemoryERROR1.java 힙 오버플로
매개변수
:-Xms 힙 최소 값;- :-Xss는 스택 값
//递归来StackOverFlowerpublic class JavaVMStackSOF {private int stackLength = 1;public void stackLeak(){ stackLength++; stackLeak(); }public static void main(String[] args)throws Throwable{ JavaVMStackSOF oom = new JavaVMStackSOF();try { oom.stackLeak(); } catch(Throwable e){ System.out.println("stack length:" + oom.stackLength);throw e; } } }
3. 메소드 영역 및 상수 풀 오버플로
Parameter: -XX:PermSize 메소드 영역 크기 ;-XX: MaxPermSize 메소드 영역의 최대 크기
1.7 이상에서는 이것이 허용되지 않습니다. 가상 머신은 객체가 상수 풀에 처음 나타날 때만 객체에 대한 참조를 저장하기 때문입니다
public class JavaMethodAreaOOM{public static void main(String[]args){while(true){//创建大量的动态类,动态代理OOMObjectEnhancer enhancer=new Enhancer(); enhancer.setSuperclass(OOMObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor(){public Object intercept(Object obj,Method method,Object[]args,MethodProxy proxy)throws Throwable{return proxy.invokeSuper(obj,args); }} ); enhancer.create(); }}static class OOMObject{ } }를 사용합니다.
String.intern()은 기본 메서드입니다. 해당 기능은 다음과 같습니다. 문자열 상수 풀에 이미 이 String 개체와 동일한 문자열이 포함되어 있으면 풀의 문자열을 나타내는 문자열입니다. 그렇지 않으면 이 String 객체에 포함된 문자열이 상수 풀에 추가되고 이 String 객체에 대한 참조가 반환됩니다. 세대)가 분리되어 있으며 상수 풀은 메소드 영역 Inside JDK7: 영구 세대로 이동
public class RuntimeConstantPoolOOM{public static void main(String[]args){ String str1=new StringBuilder("计算机").append("软件").toString(); System.out.println(str1.intern()==str1); String str2=new StringBuilder("ja").append("va").toString(); System.out.println(str2.intern()==str2); } }
이 코드를 JDK 1.6에서 실행하면 false 2개를 얻지만, JDK 1.7에서 실행하면 true 1개와 false 1개를 얻습니다.
차이가 나는 이유는 JDK 1.6에서 intern() 메서드는 처음 발견된 문자열 인스턴스를 영구 세대에 복사하고 영구 세대의 문자열 인스턴스에 대한 참조를 반환하는 반면 StringBuilder에서 생성한 문자열 인스턴스는 string 인스턴스는 Java 힙에 있으므로 동일한 참조가 아니어야 하며 false가 반환됩니다.
JDK 1.7: intern() 구현은 더 이상 인스턴스를 복사하지 않고 상수 풀에서 가 처음 나타나는 인스턴스 참조만 기록하므로 intern()에서 반환된 참조는 생성된 문자열 인스턴스와 동일합니다. StringBuilder로.
StringBuilder.toString()을 실행하기 전에 문자열 "java"가 이미 나타나고 문자열 상수 풀에 이에 대한 참조가 이미 있으므로 str2의 비교는 false를 반환합니다. 이는 "첫 번째 출현" 원칙을 따르지 않습니다. , ""Computer Software"라는 문자열이 처음 등장하므로 true를 반환합니다참고: 1.7 이상에서는 처음 나타나는 참조를 저장합니다. 위 분석을 이해하세요
4. 네이티브 직접 메모리위 내용은 Java 메모리 영역 및 메모리 오버플로 예외에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!