jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置

堆(Heap)
在jdk1.7以前:

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第1张图片

jdk1.8:永久区变成了元空间

堆在物理上分为:新生+养老(真正干活的就这两个)

讲一下堆中物理划分出两个:新生区+养老区:(真正干活的就这两个)

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第2张图片

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第3张图片

 

新生区中伊甸区的GC称为Minor GC;
养老区的GC称为Major GC(Full GC);
 
堆从物理上分为新生区+养老区(真正干活的就这两个)

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第4张图片

伊甸区的GC又可以称为YGC;
1.伊甸区满了(假设100个),需要GC,GC之后存活的对象,不会留在伊甸区,而是进入幸存者0区-S0-From(以复制的方式,将伊甸区的对象复制到幸存者0区,并删除伊甸园区存活下来的那个已经被复制过的原样本(因为:伊甸园区只要GC,一定会被清空!)),并给该对象年龄+1(用于累积计算经历GC并依然没有被清理的次数,到15次后,进入养老区);
2.现在在伊甸区又满了,需要GC(是对伊甸区+S0区, 两个区一起GC),假设伊甸区又存活1个,同样以复制的方式放进S0,并清空伊甸区。(现在伊甸区有0个对象,S0有2个对象)(现在需要考虑一个东西:交换!!!)--->会将这两个对象(伊甸区1个,S0区1个)复制,拷贝到To区,拷贝之后有交换,上一步的From清空变为To,To由于拷贝过来了2个对象,变为From区。(年龄+1,别忘了)(现在伊甸区和From区都为空,To区2个对象,经过交换,To区变为From(有2个对象),空的From变为To区(即所谓的谁空谁是To))

所以,年轻代gc的原理,总结为两个词: 复制+交换

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第5张图片

默认   -XX:MaxTenuringThreshold=15         表示新生代需要经历多少次GC晋升到老年代中的最大阈值

 

 


???字符串常量池jdk1.8在元空间中 (字符串常量池从jdk1.7开始,从原本的方法区移走,放进了堆里)
???jdk1.7中,已经将原本放在永久代的字符串常量池移走。(放进堆里)

 

jdk1.6 永久代(方法区的实现) 字符串常量池放在方法区(永久代)
jdk1.7 永久代(方法区的实现) 字符串常量池移到了堆里
jdk1.8 方法区(方法区的实现) 字符串常量池放在堆里

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第6张图片

jdk1.7对方法区的落地实现,叫永久代;
jdk1.8对方法区的落地实现,叫元空间。

方法区由所有线程共享,可以理解成一个接口,用于存储类模板Class(由JVM装载器加载.class得来)
方法区逻辑上属于堆,物理上不属于堆
jdk1.7中,将原本放在永久代中的字符串常量池移走了。(对,放进了堆)

所以,讲永久代、元空间,实际就是在讲方法区:

jvm - 堆的新生代和老年代 & 年轻代gc回收过程 & OutOfMemoryError & 永久代和元空间关系 & 字符串常量池在不同jdk版本的位置_第7张图片

因为永久代存放的是jdk类的模板信息,所以除非JVM别关闭,被装在进永久代这个常驻内存区域中的数据是不会被回收掉的。

可通过-XX:PermSize和-XX:MaxPermSize来指定永久代的初始值和最大值

你可能感兴趣的:(jvm)