jvm gc机制说明
1 GC的方式与过程
参考文档 https://blog.51cto.com/u_14962799/2739752
关键词:伊甸园区,幸存区,年轻代,年老代,持久代

JVM内存的大致结构
- 年轻代(young generation)
- 两个幸存区(survivor)
- 一个伊甸区(eden)
- 老年代(old generation)
- 吃就带(perm)
GC的工作过程
- 持久代:当类加载时,我们会将.class文件中的部分信息加载到持久区中,比如类的修饰符,字段属性和方法信息等。又或者时import引入类的信息。都叫持久代了,也就说明这块区间的内存相对稳定,垃圾回收一般也就没持久代啥事儿。
- 伊甸园区:伊甸园区好理解,希腊神话中人类诞生的地方。因此,当我们创建对象时,比如:new String(“123”);即JVM在伊甸园区创建了一个对象,对象里面装的是String类型的数据123。
- 幸存区:当伊甸园区的内存占满了,而又需要创建对象时,JVM就会像伊甸园区还活着的(被引用的对象),拷贝到幸存区去。此时其实会调用一此Minor GC操作,也可以称为迷你的垃圾回收动作,该动做就会将没有被引用的对象回收了。然后程序继续运行,当伊甸园和其中一个幸存区(幸存区1)都满了的时候,此时又会执行一次Minor GC,该次垃圾回收会将伊甸园区和幸存区1中所有还活着的对象(仍然被引用的)复制到幸存区2中,然后将没有用的对象回收。
- 老年代:当需要创建对象,而伊甸园区和幸存区都装满了的时候,就会将年轻代活着的的对象复制到老年代中,此时又会唤起Minor GC操作,将没有被引用的对象回收。但是我们常讨论的,其实还是Full GC,即当老年代内存占满了的时候,JVM会触发Full GC,也就是重量级的垃圾回收机制。
- Full GC:Full GC会对年轻代,年老代,持久代的对象进行全面回收。但是垃圾回收线程并不会中断其他的线程,而是并发执行的。在真正回收垃圾之前,会先根据根搜索算法,找到可以回收的对象,并对其进行标记。但是如果先将对象标记了可回收,但是后面有给这个指向null的对象str指向了“123”这块内存时,这个对象就不应该被回收。那么就会出现这个对象到底应不应该回收的问题。JVM为了解决这个问题,会在一些特定的位置上设置一些“安全点”,比如容易抛异常的地方或者循环的末尾,当垃圾回收进程运行到这些安全点时,就会执行stop the word命令,暂停所有线程,只运行垃圾回收线程。这也就是内存满了容易卡的原因。当堆内存快要用完时,就会Full GC,此时可能会出发stop the word,当GC之后,内存还是不够用,此时还会再次执行Full GC,此时还有可能会触发stop the word。因此,我们需要合理的写代码,尽量避免创建不用的对象以及避免无用对象无法回收,当然,配置好堆内存的各个区的比例,按需配置,也是必要的。也可以简单的来说,JVM调优,在一定程度上,就是配置堆内存中各个区间的大小。
2 如何判断单对象是否可以回收
- 早期的JDK采用的是“引用计数法”来判断对象是否可以被回收。当一个对象被创建时,其计数为0,当其被a引用时,计数+1,但是当a = null;时,计数-1,那么当计数为0时,该对象即可被回收,但是这样子的算法,有个缺陷,就是循环引用的对象无法被回收。
- 后来改用“根搜索算法”标记可回收对象,将根节点不可达的对象进行标记。
3 何时Full GC呢?
1:老年代被写满了
2:持久代被写满了
3:当调用了system.gc();
4:当用命令分配堆空间的运行策略时,比如设置年轻代和老年代的比例。如果JVM发现,上次GC后,这种运行策略有了变化,就会触发GC。
4 JVM调优,调整哪些参数
1 | -Xms:初始堆大小,默认是物理内存的1/64。默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到–Xmx的最大限制。例如:-Xms 500m。 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Estom的博客!










