자바 가상 컴퓨터 스 택 및 메모리 모델 깊이 이해

1.바이트 코드 명령 을 결합 하여 자바 가상 컴퓨터 스 택 과 스 택 프레임 을 이해 합 니 다.
스 택 프레임:모든 스 택 프레임 은 호출 된 방법 에 대응 하여 하나의 방법의 운행 공간 으로 이해 할 수 있 습 니 다.
모든 스 택 프레임 에는 부분 변수 표(Local Variables),작업 스 택(Operand Stack),실행 시 상 당량 풀 을 가리 키 는 참조(A reference to the run-time constant pool),방법 반환 주소(Return Address)와 추가 정보 가 포함 되 어 있 습 니 다.
부분 변수 표:방법 에서 정 의 된 부분 변수 와 방법의 매개 변 수 는 이 표 에 저장 되 어 있 습 니 다.부분 변수 표 의 변 수 는 직접 사용 할 수 없습니다.만약 에 사용 하려 면 관련 명령 을 통 해 이 를 조작 수 스 택 에 불 러 와 조작 수 로 사용 해 야 합 니 다.
작업 수 스 택:스 택 을 누 르 고 스 택 을 나 가 는 방식 으로 작업 수 를 저장 합 니 다.
동적 링크:모든 스 택 프레임 은 런 타임 풀 에서 이 스 택 프레임 에 속 하 는 방법 에 대한 인용 을 포함 하고 있 습 니 다.이 인용 을 가지 고 있 는 것 은 방법 호출 과정 에서 의 동적 연결(Dynamic Linking)을 지원 하기 위해 서 입 니 다.
방법 반환 주소:한 방법 이 실 행 된 후에 두 가지 방법 만 종료 할 수 있 습 니 다.하 나 는 방법 에 따라 되 돌아 오 는 바이트 코드 명령 입 니 다.하 나 는 이상 을 만 났 고 이 이상 은 방법 내 에서 처리 되 지 않 았 다.
在这里插入图片描述

class Person{
    private String name="Jack";
    private int age;
    private final double salary=100;
    private static String address;
    private final static String hobby="Programming";
   
    public void say(){
        System.out.println("person say..."); 
    }
    
    public static int calc(int op1,int op2){
        op1=3;
        int result=op1+op2;
        return result;
    }
    
    public static void order(){
    }
    
    public static void main(String[] args){
        calc(1,2);
        order(); 
    }
}

Compiled from "Person.java" class Person {
...
  public static int calc(int, int);
    Code:
        0: iconst_3 // int    3  [    ]
        1: istore_0 // int     [    0]
        2: iload_0  // [    0]   int     
        3: iload_1  // [    1]   int     
        4: iadd //        ,  int     ,    
        【For example, the iadd instruction (§iadd) adds two int values together. It requires that the int values to be added be the top two values of the operand stack, pushed there by previous instructions. Both of the int values are popped from the operand stack. They are added, and their sum is pushed back onto the operand stack. Subcomputations may be nested on the operand stack, resulting in values that can be used by the encompassing computation.】
        5: istore_2 //   int      [    2] 
        6: iload_2  // [    2]   int     
        7: ireturn  //      int     
...
}
在这里插入图片描述
2.깊이 분석
2.1 스 택 지향 더미
만약 에 스 택 프레임 에 변수 가 있 으 면 유형 은 참조 형식 입 니 다.예 를 들 어 Object obj=new Object()는 전형 적 인 스 택 에서 요소 가 쌓 인 대상 을 가리 키 는 것 입 니 다.
在这里插入图片描述
2.2 방법 영역 지향 더미
방법 영역 에 정적 변수,상수 등 데 이 터 를 저장 합 니 다.아래 와 같은 상황 이 라면 전형 적 인 방법 구역 에서 요소 가 더미 속 의 대상 을 가리 키 는 것 이다.

private static Object obj=new Object();
在这里插入图片描述
2.3 더미 지향 방법 영역
방법 구역 에는 클래스 의 정보 가 포함 되 어 있 습 니 다.더미 에 대상 이 있 습 니 다.대상 이 어떤 클래스 로 만 들 어 졌 는 지 어떻게 압 니까?
在这里插入图片描述
사고:대상 이 어떤 종류 로 만 들 어 졌 는 지 어떻게 압 니까?어떻게 기록 합 니까?자바 대상 에 대한 구체 적 인 정 보 를 알 아야 합 니 다.
2.4 Java 개체 메모리 레이아웃
하나의 자바 대상 은 메모리 에 세 부분 을 포함 합 니 다.대상 헤드,인 스 턴 스 데이터 와 정렬 충전 입 니 다.
在这里插入图片描述
3.메모리 모델
 3.1 도해
하 나 는 시비 더미 구역 이 고,하 나 는 더미 구역 이다.
더 미 는 두 개의 큰 덩어리 로 나 뉘 는데 하 나 는 Old 구역 이 고 하 나 는 Young 구역 이다.영 은 두 개의 큰 덩어리 로 나 뉘 는데 하 나 는 서 바 이 버 구역(S0+S1)이 고 하 나 는 에덴 구역 이다.Eden:S0:S1=8:1:1 S10 은 S1 만큼 크 고 From 와 To 라 고도 할 수 있 습 니 다.
在这里插入图片描述
이전 힙 에 대한 설명 을 통 해 알 수 있 듯 이 일반 대상 과 배열 의 생 성 은 더미 에서 메모리 공간 을 분배 합 니 다.관건 은 더미 에 이렇게 많은 구역 이 있 는데 그 대상 의 생 성 은 도대체 어느 구역 에 있 습 니까?
3.2 대상 이 있 는 영역 만 들 기
일반적으로 새로 만 든 대상 은 Eden 구역 에 배정 되 고 일부 특수 한 큰 대상 은 Old 구역 에 직접 배정 된다.
예 를 들 어 대상 A,B,C 등 이 Eden 구역 에 만 들 어 졌 지만 Eden 구역 의 메모리 공간 은 한계 가 있 을 것 입 니 다.예 를 들 어 100 M 을 사 용 했 거나 설 정 된 임계값 에 이 르 렀 다 면 Eden 메모리 공간,즉 쓰레기 수집(Garbage Collect)을 청소 해 야 합 니 다.이런 GC 를 우 리 는 Minor GC 라 고 부 릅 니 다.Minor GC 는 Young 구역 의 GC 를 말 합 니 다.
GC 를 거 친 후에 일부 대상 은 정리 되 고 일부 대상 은 살아 있 을 수 있 으 며 살아 있 는 대상 에 대해 서 는 Survivor 구역 으로 복사 한 다음 에 Eden 구역 의 이 대상 들 을 비 워 야 한다.
3.3 Survivor 구역 에 대한 상세 한 설명
도 해 를 보면 Survivor 는 두 개의 S0 과 S1 로 나 뉘 는데 From 와 To 라 고도 할 수 있다.같은 시점 에서 S0 과 S1 은 한 구역 만 데이터 가 있 을 수 있 고 다른 하 나 는 비어 있다.
이 어 위의 GC 의 경우 처음에 Eden 구역 과 From 에 만 대상 이 있 었 고 To 중 은 비어 있 었 다.이때 GC 작업 을 한 번 하면 From 구역 에서 대상 의 나이 가+1 이 되 고 우 리 는 Eden 구역 에서 살아 남 은 모든 대상 이 To 구역 으로 복 사 될 것 이라는 것 을 알 고 있 습 니 다.
From 구역 에서 살아 남 을 수 있 는 대상 은 두 곳 이 있 을 것 이다.
대상 연령 이 이전에 설정 한 연령 한도 값 에 도달 하면 대상 은 Old 구역 으로 이동 하고,1113088:1113089:Eden:1113090:1113091:From:1113090:한도 값 에 도달 하지 못 한 대상 은 To 구역 으로 복 사 됩 니 다.이때 에덴 구 와 프 롬 구 는 이미 비 워 졌 다.
이때 From 와 To 는 캐릭터 를 주 고 받 았 고,이전의 From 는 To 로,이전의 To 는 From 로 바 뀌 었 다.어떻게 든 To 라 는 Survivor 구역 이 비어 있다 는 것 을 보증 해 야 한 다 는 것 이다.
마 이 너 GC 는 To 구역 이 채 워 질 때 까지 이러한 과정 을 반복 한 뒤 모든 대상 을 옛날 로 복사 합 니 다.
3.4 오래된 지역 에 대한 상세 한 설명
위의 분석 을 통 해 알 수 있 듯 이 일반 Old 구역 은 나이 가 비교적 많은 대상 이거 나 특정한 한도 값 을 상대 적 으로 초과 한 대상 이다.
Old 구역 에서 도 GC 의 조작 이 있 습 니 다.Old 구역 의 GC 는 Major GC 라 고 합 니 다.
3.5 대상 의 평생 이해
저 는 평범한 자바 대상 입 니 다.저 는 Eden 지역 에서 태 어 났 습 니 다.Eden 지역 에서 저 와 닮 은 동생 도 보 았 습 니 다.우 리 는 Eden 지역 에서 오랫동안 놀 았 습 니 다.어느 날 Eden 구역 에 사람 이 너무 많아 서 저 는 Survivor 구역 의'From'구역 에 갈 수 밖 에 없 었 습 니 다.Survivor 구역 에 간 후부 터 저 는 표류 하기 시 작 했 습 니 다.가끔 은 Survivor 의'From'구역 에 있 고 가끔 은 Survivor 의'To'구역 에 있 으 며 정처 가 없 었 습 니 다.내 가 열 여덟 살 이 되 었 을 때 아버 지 는 내 가 성인 이 되 었 으 니 사회 에 나 가 야 한다 고 말씀 하 셨 다.그래서 저 는 늙 은 세대 에 갔 습 니 다.늙 은 세대 에 사람 이 많 고 나이 도 많 습 니 다.저 는 여기 서 많은 사람들 을 알 게 되 었 습 니 다.연로 한 세대 에 나 는 20 년(매번 GC 에 한 살 씩)을 살다 가 회수 되 었 다.
在这里插入图片描述
3.6 흔히 볼 수 있 는 문제
  •  어떻게 Minor/Major/Full GC
  • 을 이해 합 니까?
    Minor GC:신세대
    주요 GC:구세대
    Full GC:신세대+노년기
  • 왜 Survivor 구역 이 필요 합 니까?에덴 만 있 으 면 안 돼 요?
  • 서 바 이 버 가 없 었 다 면 에덴 구 는 마 이 너 GC 를 한 번 씩 진행 할 때마다 생존 대상 이 옛날 로 보 내 졌 을 것 이다.이렇게 되면 옛 연대 가 빠르게 채 워 져 Major GC 를 촉발 시킨다(Major GC 는 일반적으로 Minor GC 를 수반 하고 Full GC 를 촉발 한 것 으로 볼 수 있 기 때문이다).오래된 시대 의 메모리 공간 은 신세대 보다 훨씬 컸 고 Full GC 를 한 번 진행 하 는 데 소모 되 는 시간 은 Minor GC 보다 훨씬 길 었 다.집행 시간 이 길 면 어떤 나 쁜 점 이 있 습 니까?빈발 하 는 Full GC 는 오래 걸 려 대형 프로그램의 실행 과 응답 속도 에 영향 을 줄 수 있다.
    옛 시대 의 공간 을 늘 리 거나 적 게 만 들 겠 다 고 말 할 수도 있다.옛 시대 의 공간 을 늘 려 야 더 많은 생존 대상 이 옛 시 대 를 채 울 수 있다.풀 GC 주파 수 를 낮 추 긴 했 지만,노후 공간 이 커지 면서 풀 GC 가 발생 하면 실행 에 걸 리 는 시간 이 더 길 어 졌 다.
    노후 공간 을 줄 이면 풀 GC 에 걸 리 는 시간 은 줄 어 들 지만,노후 에는 곧 생존 대상 으로 채 워 져 풀 GC 주파수 가 증가한다.
    그래서 Survivor 의 존재 의 미 는 바로 옛날 로 보 내 지 는 대상 을 줄 이 고 Full GC 의 발생 을 줄 이 는 것 이다.Survivor 의 예비 선별 보증 은 16 번 의 Minor GC 를 거 쳐 신세대 에서 살아 남 을 수 있 는 대상 만 옛날 로 보 내 지 는 것 이다.
  • 왜 두 개의 Survivor 구역 이 필요 합 니까?
  • 가장 큰 장점 은 파편 화 를 해결 하 는 것 이다.그 러 니까 왜 Survivor 구역 이 안 되 는 거 야?첫 번 째 부분 에서 우 리 는 Survivor 구역 을 설치 해 야 한 다 는 것 을 알 게 되 었 다.만약 에 현재 Survivor 구역 이 하나 밖 에 없다 고 가정 하면 우 리 는 절 차 를 모 의 해 보 겠 습 니 다.
    새로 만 든 대상 은 Eden 에 있 습 니 다.Eden 이 가득 차 면 Minor GC 를 한 번 터치 하면 Eden 의 생존 대상 은 Survivor 구역 으로 이동 합 니 다.이렇게 계속 순환 하면 다음 에덴 이 꽉 찼 을 때 문제 가 생 겼 다.이때 Minor GC,Eden 과 Survivor 는 각각 생존 대상 이 있다.만약 에 이때 Eden 구역 의 생존 대상 을 Survivor 구역 에 억지로 두 면 이 두 부분 대상 이 차지 하 는 메모리 가 계속 되 지 않 고 메모리 파편 화 를 초래 한 것 이 분명 하 다.
    영원히 하나의 Survivor space 는 비어 있 고,다른 하 나 는 비어 있 지 않 은 Survivor space 는 조각 이 없다.
  • 신세대 중 Eden:S1:S2 는 왜 8:1 입 니까?
  • 신세대 의 사용 가능 한 메모리:복제 알고리즘 이 담보 하 는 메모리 9:1
    사용 가능 한 메모리 중 Eden:S1 구역 은 8:1 입 니 다.
    즉 신생대 중 에덴:S1:S2=8:1:1
    4.검증
    4.1 더미 메모리 넘 침
    프로그램:
    
    @RestController
    public class HeapController {
        List<Person> list=new ArrayList<Person>();
        @GetMapping("/heap")
        public String heap() throws Exception{
            while(true){
                list.add(new Person()); 
                Thread.sleep(1);
            } 
        }
    }
    
    인 자 를 설정 하 세 요.예 를 들 어-Xmx20M-Xms20M.
    실행 결과:
    
    Exception in thread "http-nio-8080-exec-2" java.lang.OutOfMemoryError: GC overhead limit exceeded
    4.2 방법 영역 메모리 넘 침
    예 를 들 어 방법 영역 에 Class 정 보 를 추가 합 니 다.
    4.2.1 asm 의존 과 Class 코드
    
    <dependency> 
        <groupId>asm</groupId> 
        <artifactId>asm</artifactId> 
        <version>3.3.1</version>
    </dependency>
    public class MyMetaspace extends ClassLoader {
        public static List<Class<?>> createClasses() {
            List<Class<?>> classes = new ArrayList<Class<?>>();
            for (int i = 0; i < 10000000; ++i) {
                ClassWriter cw = new ClassWriter(0);
                cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Class" + i, null,
                "java/lang/Object", null);
                MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
                "()V", null, null);
                mw.visitVarInsn(Opcodes.ALOAD, 0); mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
                "<init>", "()V"); mw.visitInsn(Opcodes.RETURN);
                mw.visitMaxs(1, 1);
                mw.visitEnd();
                Metaspace test = new Metaspace();
                byte[] code = cw.toByteArray();
                Class<?> exampleClass = test.defineClass("Class" + i, code, 0, code.length); 
                classes.add(exampleClass);
            }
            return classes;
        }
    }
    
    4.2.2 코드
    
    @RestController
    public class NonHeapController {
        List<Class<?>> list=new ArrayList<Class<?>>();
        @GetMapping("/nonheap")
        public String nonheap() throws Exception{
            while(true){ 
            list.addAll(MyMetaspace.createClasses()); 
            Thread.sleep(5);
            } 
        }
    }
    
    Metaspace 의 크기 를 설정 합 니 다.예 를 들 어-XX:MetaspaceSize=50M-XX:MaxMetaspaceSize=50M
    실행 결과:
    
    java.lang.OutOfMemoryError: Metaspace
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_191]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_191]
    
    4.3 가상 컴퓨터 스 택
     4.3.1 코드 데모 StackOverFlow
    
    public class StackDemo {
        public static long count=0;
        public static void method(long i){
            System.out.println(count++);
            method(i); 
        }
        public static void main(String[] args) {
            method(1);
        }
    }
    
    실행 결과:
    在这里插入图片描述
    4.3.2 이해 와 설명
    Stack Space 는 재 귀적 호출 을 할 때 Stack Frame(스 택 프레임)을 누 릅 니 다.따라서 재 귀적 호출 이 너무 깊 을 때 Stack Space 를 다 소모 하여 Stack Overflow 의 오 류 를 폭로 할 수 있 습 니 다.
    -Xss 128 k:스 레 드 마다 스 택 크기 를 설정 합 니 다.JDK 5 이후 모든 스 레 드 스 택 크기 는 1M 이 고 이전 에는 스 레 드 스 택 크기 가 256 K 였 습 니 다.응용 스 레 드 에 필요 한 메모리 크기 를 조정 합 니 다.같은 물리 적 메모리 에서 이 값 을 줄 이면 더 많은 스 레 드 를 만 들 수 있 습 니 다.그러나 운영 체 제 는 한 프로 세 스 의 스 레 드 수 에 제한 이 있어 무한 생 성 이 불가능 하고 경험 치 는 3000~5000 정도 입 니 다.
    스 레 드 스 택 의 크기 는 양날 의 검 입 니 다.너무 작 게 설정 하면 스 택 이 넘 칠 수 있 습 니 다.특히 이 스 레 드 에 재 귀적 이 고 큰 순환 이 있 을 때 넘 칠 가능성 이 더 큽 니 다.이 값 을 너무 크게 설정 하면 스 택 을 만 드 는 수량 에 영향 을 줄 수 있 습 니 다.다 중 스 레 드 를 사용 하면 메모리 가 넘 치 는 오류 가 발생 할 수 있 습 니 다.
    자바 가상 머 신 스 택 과 메모리 모델 에 대해 깊이 있 게 알 고 있 는 이 글 은 여기까지 소개 되 었 습 니 다.자바 가상 머 신 스 택 과 메모리 모델 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기