Files
notes_estom/Java/JVM原理/jvm gc机制说明.md
2024-02-27 11:33:00 +08:00

4.9 KiB
Raw Blame History

1 GC的方式与过程

参考文档 https://blog.51cto.com/u_14962799/2739752 关键词:伊甸园区,幸存区,年轻代,年老代,持久代

JVM内存的大致结构

  • 年轻代young generation
    • 两个幸存区survivor
    • 一个伊甸区eden
  • 老年代old generation
  • 吃就带perm

GC的工作过程

  1. 持久代:当类加载时,我们会将.class文件中的部分信息加载到持久区中比如类的修饰符字段属性和方法信息等。又或者时import引入类的信息。都叫持久代了也就说明这块区间的内存相对稳定垃圾回收一般也就没持久代啥事儿。
  2. 伊甸园区伊甸园区好理解希腊神话中人类诞生的地方。因此当我们创建对象时比如new String("123")即JVM在伊甸园区创建了一个对象对象里面装的是String类型的数据123。
  3. 幸存区当伊甸园区的内存占满了而又需要创建对象时JVM就会像伊甸园区还活着的被引用的对象拷贝到幸存区去。此时其实会调用一此Minor GC操作也可以称为迷你的垃圾回收动作该动做就会将没有被引用的对象回收了。然后程序继续运行当伊甸园和其中一个幸存区幸存区1都满了的时候此时又会执行一次Minor GC该次垃圾回收会将伊甸园区和幸存区1中所有还活着的对象(仍然被引用的)复制到幸存区2中然后将没有用的对象回收。
  4. 老年代当需要创建对象而伊甸园区和幸存区都装满了的时候就会将年轻代活着的的对象复制到老年代中此时又会唤起Minor GC操作将没有被引用的对象回收。但是我们常讨论的其实还是Full GC即当老年代内存占满了的时候JVM会触发Full GC也就是重量级的垃圾回收机制。
  5. Full GCFull GC会对年轻代年老代持久代的对象进行全面回收。但是垃圾回收线程并不会中断其他的线程而是并发执行的。在真正回收垃圾之前会先根据根搜索算法找到可以回收的对象并对其进行标记。但是如果先将对象标记了可回收但是后面有给这个指向null的对象str指向了“123”这块内存时这个对象就不应该被回收。那么就会出现这个对象到底应不应该回收的问题。JVM为了解决这个问题会在一些特定的位置上设置一些“安全点”比如容易抛异常的地方或者循环的末尾当垃圾回收进程运行到这些安全点时就会执行stop the word命令暂停所有线程只运行垃圾回收线程。这也就是内存满了容易卡的原因。当堆内存快要用完时就会Full GC此时可能会出发stop the word当GC之后内存还是不够用此时还会再次执行Full GC此时还有可能会触发stop the word。因此我们需要合理的写代码尽量避免创建不用的对象以及避免无用对象无法回收当然配置好堆内存的各个区的比例按需配置也是必要的。也可以简单的来说JVM调优在一定程度上就是配置堆内存中各个区间的大小。

2 如何判断单对象是否可以回收

  1. 早期的JDK采用的是“引用计数法”来判断对象是否可以被回收。当一个对象被创建时其计数为0当其被a引用时计数+1但是当a = null计数-1那么当计数为0时该对象即可被回收但是这样子的算法有个缺陷就是循环引用的对象无法被回收。
  2. 后来改用“根搜索算法”标记可回收对象,将根节点不可达的对象进行标记。

3 何时Full GC呢

1老年代被写满了 2持久代被写满了 3当调用了system.gc(); 4当用命令分配堆空间的运行策略时比如设置年轻代和老年代的比例。如果JVM发现上次GC后这种运行策略有了变化就会触发GC。

4 JVM调优调整哪些参数

-Xms:初始堆大小默认是物理内存的1/64。默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时JVM就会增大堆直到Xmx的最大限制。例如-Xms 500m。
-Xmx:最大堆大小。默认是物理内存的1/4 默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时JVM会减少堆直到 -Xms的最小限制。
-XX:NewSize设置年轻代大小初始值。
-XX:MaxNewSize设置年轻代最大值。
**-XX:NewRatio=n设置年轻代和年老代的比值。一般设置为4
-XX:SurvivorRatio=n年轻代中Eden区与两个Survivor区的比值。
-XX:PermSize1.8之后改为MetaspaceSize 设置持久代(perm gen)初始值默认是物理内存的1/64。
-XX:MaxPermSize=n:1.8之后改为MaxMetaspaceSize设置最大持久代大小。
-Xss每个线程的堆栈大小。所有当项目经常发生栈内存溢出(stackOverflowErro)时,可以考虑增加该参数大小