Interviewer : 온라인 JVM이 어떻게 최적화되었는지 알려주세요. 실수로 2 시간 동안 채팅을했습니다! !

Interviewer : 온라인 JVM이 어떻게 최적화되었는지 알려주세요. 실수로 2 시간 동안 채팅을했습니다! !

JVM의 메모리 모델은 어떻게 생겼습니까? 개체는 언제 복구 할 수 있습니까? 일반적인 가비지 수집기 알고리즘은 무엇이며 장점과 단점은 무엇입니까? 피험자는 언제 노년에 들어 갑니까? 공간 할당 보장 전략은 무엇입니까? Full
GC 를 최적화하고 줄이는 방법은 무엇입니까?

이 거대한 JVM 인터뷰 질문에 직면했을 때, 당신은 정말로 살아 있습니까?

모든 사람이 지식 프레임 워크의 기본 개요를 알 수 있도록 핵심 지식 포인트이든 인터뷰 질문이든 중요한 지식 포인트를 여기에 적어 놓았습니다.
동시에 Java의 핵심 지식 포인트이기도 한 PDF 문서 283 페이지도 구성되어 있습니다.
도움이 필요한 친구는 여기를 클릭하여받을 수 있습니다! ! ! , 코드 : CSDN

여기에 사진 설명 삽입

JVM 메모리 모델은 어떻게 생겼습니까?

JVM 메모리 모델은 크게 쓰레드 전용 영역과 공유 영역으로 나눌 수 있으며, 스레드 전용 영역은 가상 머신 스택, 로컬 메소드 스택, 프로그램 카운터로 구성되고 공유 영역은 힙과 메타 데이터 공간 (메소드 영역)으로 구성됩니다.여기에 사진 설명 삽입

누군가 JVM의 메모리 모델에 대해 물어 보면 위의 그림을 떠올려보십시오.하지만 여전히 JVM의 메모리 모델을 아는 것은 좋지 않습니다. 또한 그들이 무엇을하는지 알아야합니다.

가상 머신 스택 / 로컬 메소드 스택

StackOverflowException 예외를 만났을 때 왜 그런 예외가 발생했는지 생각 했습니까? 그 답은 가상 머신 스택에 있으며 JVM은 각 메소드에 대한 스택 프레임을 생성 한 다음 스택 프레임을 가상 머신 스택으로 푸시합니다.

예를 들어, JVM 매개 변수 -Xss가 1m로 설정되고 128kb 배열이 메소드에 생성 된 경우이 메소드는 동일한 스레드에서 4 번만 재귀 할 수 있으며 다섯 번째로 재귀 할 경우 StackOverflowException을보고합니다. , 가상 머신 스택의 크기가 1m에 불과하기 때문에 각 재귀는 방법에 대해 가상 머신 스택에 128kb의 공간을 할당해야합니다. 이는 다섯 번째로 공간이 부족함을 나타냅니다.
여기에 사진 설명 삽입

프로그램 카운터

프로그램 카운터는 현재 스레드가 실행 한 바이트 코드를 기록하는 라인 표시기입니다. JVM의 멀티 스레딩은 CPU 시간 슬라이스 회전 (즉, 스레드가 차례로 전환되고 프로세서 실행 시간을 할당) 알고리즘에 의해 실현됩니다. 즉, 실행 중 타임 슬라이스가 소진되어 쓰레드가 일시 중지되고 다른 쓰레드가 타임 슬라이스를 획득하여 실행을 시작하는 것이다.

简单的说程序计数器的主要功能就是记录着当前线程所执行的字节码的行号指示器。

方法区(元数据区)

方法区存储了类的元数据信息、静态变量、常量等数据。
여기에 사진 설명 삽입

堆(heap)

平常大家使用new关键字创建的对象都会进入堆中,堆也是GC重点照顾的区域,堆会被划分为:新生代、老年代,而新生代还会被进一步划分为Eden区和Survivor区:
여기에 사진 설명 삽입

新生代中的Eden区和Survivor区,是根据JVM回收算法来的,只是现在大部分都是使用的分代回收算法,所以在介绍堆的时候会直接将新生代归纳为Eden区和Survivor区。

小结

JVM内存模型小结:

JVM内存模型划分为线程私有区域和共享区域虚拟机栈/本地方法栈负责存放线程执行方法栈帧程序计数器用于记录线程执行指令的位置方法区(元数据区)存储类的元数据信息、静态变量、常量等数据堆(heap)使用new关键字创建的对象都会进入堆中,堆被划分为新生代和老年代

什么时候对象可以被收回?

JVM判断对象回收有两种方式:引用记数、GC Roots,引用记数比较简单,JVM为每个对象维护一个引用计数,假设A对象引用计数为零说明没有任务对象引用A对象,那A对象就可以被回收了,但是引用计数有个缺点就是无法解决循环引用的问题。

GC Roots通过一系列的名为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明对象是不可用的。

在Java中,可以作为GC Roots的对象包括下面几种:

虚拟机栈中引用的对象;方法区中类静态属性引用的对象;方法区中的常量引用的对象;本地方法栈中JNI(即一般说的Native方法)的引用的对象;

小结

总的来说就是当一个对象通过GC Roots搜索不到时,说明对象可以被回收了,但什么时候回收还要看GC的心情!

常见的垃圾回收器算法有哪些,各有什么优劣?

标记清除

이 알고리즘은 마킹과 클리닝의 두 단계로 나뉩니다.
마킹 단계는 루트 세트 (GC Root)에서 스캔을 시작합니다. 객체에 도달 할 때마다 객체가 활성 상태로 표시됩니다. 스캔이 완료된 후에는 클리닝 단계가 표시되지 않습니다. 개체가 지워집니다.

그림을 사용하여 설명하십시오.
여기에 사진 설명 삽입
이 알고리즘에는 메모리 조각화를 생성하는 결함이 있습니다. 위의 그림 B에서와 같이 지워진 후에 메모리 영역을 남겨 둡니다. 나중에 큰 개체를 할당해야하는 경우 사용할 수있는 연속 메모리가 없습니다.

마크 업

마킹 및 정렬시 메모리 조각화 문제가 없으며 루트 세트 (GC Root)에서 스캔을 시작하여 마킹 한 다음 불필요한 개체를 지 웁니다. 지우기가 완료되면 메모리를 지 웁니다.
여기에 사진 설명 삽입
이런 식으로 메모리는 연속적이지만 발생하는 또 다른 문제는 매번 개체를 이동해야하므로 비용이 많이 든다는 것입니다.

알고리즘 복사

복제 알고리즘은 JVM을 두 개의 동일한 부분으로 밀어 넣고 힙이 1g로 설정되면 복제 알고리즘을 사용할 때 힙이 각각 512m의 두 영역으로 나뉩니다. 객체에 메모리를 할당 할 때 그 중 하나가 항상 할당에 사용됩니다. 할당이 꽉 차면 GC가이를 표시 한 다음 남아있는 객체를 다른 빈 영역으로 이동 한 다음 남아 있지 않은 모든 객체를 지우고 반복합니다. 처리 과정에서 항상 합리적으로 사용되지 않은 빈 영역이 있습니다.
여기에 사진 설명 삽입
두 영역이 번갈아 사용되며 가장 큰 문제는 공간 낭비로 이어지고 힙 메모리의 사용률은 50 %에 불과하다는 것입니다.

요약

JVM 재활용 알고리즘 요약 :

마크 제거는 빠르지 만 메모리 조각화를 생성합니다. 마크 조각 모음은 명확한 메모리 조각화 표시 문제를 해결하지만 매번 개체를 이동해야하므로 비용이 높습니다. 복사 알고리즘에는 메모리 조각화가없고 개체를 이동할 필요가 없지만 공간이 발생합니다. 낭비;

피험자는 언제 노년에 들어 갑니까?

새로 생성 된 객체는 처음에는 젊은 세대에 머 무르지 만 JVM이 실행됨에 따라 수명이 긴 일부 객체는 천천히 이전 세대로 이동합니다.

대상 연령에 따라

JVM会给对象增加一个年龄(age)的计数器,对象每“熬过”一次GC,年龄就要+1,待对象到达设置的阈值(默认为15岁)就会被移移动到老年代,可通过-XX:MaxTenuringThreshold调整这个阈值。
여기에 사진 설명 삽입
一次Minor GC后,对象年龄就会+1,达到阈值的对象就移动到老年代,其他存活下来的对象会继续保留在新生代中。

动态年龄判断

根据对象年龄有另外一个策略也会让对象进入老年代,不用等待15次GC之后进入老年代,他的大致规则就是,假如当前放对象的Survivor,一批对象的总大小大于这块Survivor内存的50%,那么大于这批对象年龄的对象,就可以直接进入老年代了。

여기에 사진 설명 삽입
如图上的A、B、D、E这四个对象,假如Survivor 2是100m,如果A + B + D的内存大小超过50m,现在D的年龄是10,那E都会被移动到老年代。实际上这个计算逻辑是这样的:年龄1 + 年龄2 + 年龄n的多个对象总和超过Survivor区的50%,那就会把年龄n以上的对象都放入老年代。

大对象直接进入老年代

如果设置了-XX:PretenureSizeThreshold这个参数,那么如果你要创建的对象大于这个参数的值,比如分配一个超大的字节数组,此时就直接把这个大对象放入到老年代,不会经过新生代。

这么做就可以避免大对象在新生代,屡次躲过GC,还得把他们来复制来复制去的,最后才进入老年代,这么大的对象来回复制,是很耗费时间的。

什么是空间分配担保策略?

Minor GC가 발생하기 전에 가상 머신은 이전 세대의 사용 가능한 최대 연속 공간이 새 세대의 모든 객체의 총 공간보다 큰지 확인합니다.이 공간이 더 크면 Minor GC가 안전합니다. 이보다 작 으면 가상 머신이 HandlePromotionFailure 설정 값을 확인합니다. 보증 실패 허용 여부입니다. HandlePromotionFailure = true이면 이전 세대에서 사용 가능한 최대 연속 공간이 이전 세대로 승격 된 객체의 평균 크기보다 큰지 계속 확인합니다. 이전 세대로 승격 된 객체의 평균 크기보다 크면 보조 GC가 시도되지만 이번에는 보조 GC가 여전히 위험합니다. 또는 HandlePromotionFailure = false, 대신 전체 GC를 수행하십시오.

여기에 사진 설명 삽입

Full GC를 최적화하고 줄이는 방법은 무엇입니까?

이전 문제 중 일부를 요약하고 온라인에 적용하면 JVM이 Full GC를 어떻게 최적화하고 줄여야합니까? 표준 4 코어 8G 머신을 예로 들어 보면 먼저 시스템은 4G를 예약하고 다른 4G는 다음 규칙에 따라 할당됩니다.
• 힙 메모리 : 3g 신생대 : 1.5g
• 신생대 에덴 지역 : 1228m
• 신생대 생존자 지역 : 153m
• 방법 면적 : 256m
• 가상 머신 스택 : 1m / 스레드

설정 매개 변수는 다음과 같습니다.

 
-Xms3072m
-Xmx3072m
-Xmn1536m
-Xss=1m
-XX:PermSize=256m
-XX:MaxPermSize=256m
-XX:HandlePromotionFailure
-XX:SurvivorRatio=8
 

여기에 사진 설명 삽입
초당 시스템이 차지하는 메모리 양 추정

JVM을 최적화하기 전에 먼저 시스템이 차지하는 초당 메모리 양을 추정해야합니다. 예를 들어, 일일 활동이 100 만인 쇼핑몰 시스템이있는 경우 일일 주문량은 약 20w입니다. 하루 8 시간 기준 초당 주문 서비스는 약 500 개의 요청이 있으며, 각 요청이 차지하는 메모리 양을 대략적으로 추정하고 초당 사용되는 메모리 양을 계산합니다.

초당 500 개의 요청을 가정하면 각 요청은 100k의 공간을 할당해야하며 1 초는 약 50m의 메모리를 할당해야합니다.

Minor GC를 트리거하는 빈도 계산

이전 추정에 따르면 1 초에 약 50m의 메모리를 할당해야하는 경우 Eden 영역의 공간은 1228m이고 Minor GC는 평균 25 초마다 실행됩니다.

생존자 영역이 충분한 지 확인

위 모델에 따르면 Minor GC는 25 초마다 실행되어야하며, GC 실행 중에는 젊은 세대의 모든 개체를 복구 할 수 없으며 초당 50m로 GC 실행 중 복구 할 수없는 개체가 약 100m가됩니다. Survivor 영역에 들어가지만 JVM에는 동적 연령 결정 메커니즘이 있으므로 Survivor의 공간이 훨씬 더 작다는 것을 잊지 마십시오. 따라서 동적 연령 결정이 트리거되지 않도록 새로운 세대를 2048m로 설정하십시오.

-Xms3072m
-Xmx3072m
-Xmn2048m
...

큰 물체가 직접 노년기에 들어갑니다.

대형 오브젝트는 일반적으로 수명이 길고 사용되는 오브젝트입니다. 일반적으로 말하면 1M 오브젝트가 노년기에 직접 설정되어 젊은 세대에서 대형 오브젝트가 앞뒤로 복사되는 것을 방지하므로 PretenureSizeThreshold = 1m 매개 변수를 추가하십시오.

 
...
-XX:PretenureSizeThreshold=1m
...

개체의 연령 임계 값을 합리적으로 설정합니다.

Minor GC가 기본적으로 15 개의 가비지 컬렉션을 이스케이프하면 자동으로 노년기로 승격됩니다. 평가에 따르면 Minor GC는 25 초에 한 번씩 트리거됩니다. MaxTenuringThreshold 매개 변수의 기본값을 따르는 경우 15 개의 GC 후에는 6 분 후 여야합니다. 그러나 현재의 비즈니스 시나리오와 결합하면이를 약간 줄일 수있어 노년기에 접어 들었어야했던 객체들이 가능한 한 빨리 노년기에 진입하여 비용 복사를 피하고 신세대 공간을 낭비하여 신세대 생존자 공간이 부족하고 Full GC를 트리거 할 수 있습니다.

...
-XX:MaxTenuringThreshold=6
...
 

요약하자면

위는 모든 사람을위한 큰 공장과의 인터뷰입니다. 온라인 JVM이 어떻게 최적화되었는지 이야기하십시오. 모두에게 도움이되기를 바랍니다.

추천

출처blog.csdn.net/a3961401/article/details/108741295