美文网首页Java子弹
JVM内存分代模型(垃圾回收)

JVM内存分代模型(垃圾回收)

作者: salix_ | 来源:发表于2020-03-20 13:17 被阅读0次

    感觉网上的资料是真的少,这个也是在听了马士兵老师的课之后又结合博客,深入理解JVM三,有了总结的路线。
    一:垃圾回收针对堆区和方法区
    二:怎样找到垃圾?
    三:介绍新生代、老年代的模型(是部分垃圾回收器使用的模型)
    四:清除垃圾算法?
    五: Stop The World

    一:垃圾回收针对堆区和方法区

    hotspot在1.8之前叫永久代,1.8以及以后叫元数据空间。
    hotspot1.8和和之前的变化:
    1)移除了永久代(PermGen),替换为元空间(Metaspace);
    2)永久代中的 class metadata 转移到了 native memory(本地内存,而不是虚拟机);
    3)永久代中的 interned Strings 和 class static variables 转移到了 Java heap;(1.7就已经移除了)
    4)永久代参数 (PermSize MaxPermSize) -> 元空间参数(MetaspaceSize MaxMetaspaceSize)

    引用自《深入理解JVM三》:考虑到HotSpot未来的发展, 在JDK 6的时候HotSpot开发团队就有放弃永久代, 逐步改为采用本地内存(Native Memory) 来实现方法区的计划了[1], 到了JDK 7的HotSpot, 已经把原本放在永久代的字符串常量池、 静态变量等移出, 而到了JDK 8, 终于完全废弃了永久代的概念, 改用与JRockit、 J9一样在本地内存中实现的元空间(Metaspace) 来代替, 把JDK 7中永久代还剩余的内容(主要是类型信息) 全部移到元空间中。

    二:怎样找到垃圾?

    1.引用记数

    给每个对象打上标记,被引用一次就cnt++,如果某个对象没有引用,cnt=0,那就可以清除,但是解决不了有向环类的相互引用。


    2.Root Searching(根可达算法)
    1. 算法:标记根,从根开始搜索,根能到达的都不是垃圾,剩下的全是垃圾。
    2. 哪些是根:JVM stack(虚拟机栈栈帧里的引用对象)、方法区中类静态属性引用的变量、JNI指针指向的对象(就是Native方法)、虚拟机内部引用像NullPointerException和类加载器、Synchronized持有的对象。

    三:介绍新生代、老年代的模型(是部分垃圾回收器使用的模型)

    1.新生代、老年代介绍

    1. 垃圾回收区分为新生代、老年代。新生代又分为eden区,两个survivor。eden是干啥的?为啥要两个survivor?
    2. 注意图中默认内存大小的比例。
    3. 刚new的对象放在哪
      new一个对象默认是在eden区分配,如果对象比较大,eden放不下,直接放到老年代。
    4. 年轻代回收过程
      HotSpot虚拟机使用的是Copy算法,就是第一次进行YGC(年轻代垃圾回收,YGC不包含老年代)的时候。YGC首先把 eden该回收的回收,不该回收的放在survivor0区,age++。把eden清空,这样做可以减少eden区的空间碎片,并且效率比较高。
      survivor0的放到survivor1,survivor1的放到survivor0,都age++。如果age>cnt,那就把他放到老年代。(说明这个玩意儿用了好久,之后我们不要轻易的回收它。cnt不同的垃圾回收器是不一样的)
      这几个过程中,只要有放不下(内存)的都直接搁到老年代
    5. 老年代满了
      就进行一次Full GC,Full GC包含YGC。
      MinorGC=YGC MajorGC=FGC

    2.JDK1.8当前默认垃圾回收器

    是Parallel Scavenge(用于新生代的回收),Parallel Old(用于老年代的回收)。简称PSPO。没错是两个垃圾回收器!在JDK12不是开始收费了嘛,垃圾回收器换成了ZGC,不再用两个垃圾回收器,当然收费也贼高。ZGC就没有了新生代、老年代的概念。

    四:垃圾清理算法

    • Mark-Sweep(标记清除)
    • Copying
    • Mark-Compact(标记整理)
    1. Mark-Sweep(标记清除)

    该回收的就标记,不回收的就不管,这样做算法容易实现,复杂度也可以,但是会产生大量的碎片。

    2.Cpoying算法

    把空间分成两部分,一半永远都不使用,回收的时候,把回收的区域所有有用的对象都放到另一块干净的区域。然后擦除所有刚被回收的区域。这样做的好处是算法复杂度都可,但是浪费了大量的空间。


    3.Mark-Compact(标记整理)

    和标记清除的方法不一样,标记整理是把未回收对象集中起来放到一起。这样做有点耗时间。


    五:Stop The World

    很多人都遇到过,游戏每天半夜都要维护。还有12306每晚深夜都不能买票,这很可能就是(我可没说是,也是听来的例子)STW现象。
    对于分代回收器像我们前面提到的Parallel Scavenge、Parallel Old,GC线程在进行工作的时候,所有!是所有其他线程全部停止,等着GC线程回收完毕才能继续运行,这就是STW。像ZGC(不是分代回收器),它没有STW现象。

    相关文章

      网友评论

        本文标题:JVM内存分代模型(垃圾回收)

        本文链接:https://www.haomeiwen.com/subject/bcrkyhtx.html