【JVM】学习JVM垃圾回收理论

参考链接:https://www.cnblogs.com/aspirant/p/8662690.html

一,垃圾回收算法

JVM内存结构:程序计数器、虚拟机栈、本地方法栈、堆区、方法区

1,引用计数法:

早期JAVA使用的算法

原理:当对象被创建时,这个对象的实例会关联到一个变量进行计数,每当该实例被引用1次计数器+1,失去1个引用时,计数器减1。计数为0时,该对象处于可以被回收的状态。

优点:实时执行,应用不会挂起,只影响部分区域,不影响全部区域,速度快。

缺点:每次对象被引用,都会计数,增加了开销;并且无法解决循环引用问题。

引用计数法对象互相引用导致无法回收问题解决方案:https://www.zhihu.com/question/44079404

我能理解的有两个:

1,将循环引用的代码改成弱引用。

2,重构代码,让循环引用的场景不再出现。

其他后续的后续研究吧。

2,可达性分析算法(GCRoots):https://blog.csdn.net/qq_38844645/article/details/80494742

原理:简单地说,从根节点遍历,找到所有有关系的节点。没有引用的节点就是可以回收的对象。当没有引用的节点被扫描到后,会进行标记。下一次扫描时,才会清除这个节点。如果这个节点在下一次GC时重新建立了引用关系,则不会被回收。

优点:回收更彻底

缺点:消耗大,会造成应用停顿

3,标记-清除法:https://www.cnblogs.com/Leo_wl/p/3269590.html

原理:在JVM的堆中,从根节点遍历,找到所有存活的对象并进行标记。然后再遍历一次,找到没有被标记的进行回收

优点:不影响线程

缺点:会停止整个停止进行标记清除,所以会造成应用卡顿;因为直接回收了不存活的对象,所以会产生内存碎片。

4,复制算法

原理:复制存活的对象到另外一个空间,使存活的对象之间没有空白的内存地址?

优点:解决标记-清除法产生碎片的问题

缺点:占用双倍内存

5,标记整理算法

原理:和标记清除算法差不多,但是并不是直接回收,而是移动存活对象的内存地址,使存活对象都连在一起。

优点:

缺点:这就是FULL GC 会造成应用卡顿。

6,分代收集算法

原理:根据对象的生命周期将内存划分为不同的区域:新生代,老年代,永久代,内存分配比例为新生代:老年代=1:2,永久代呢?有一套特定的计算方法。。其中新生代分为eden区,survivor1,survivor2。按照8:1:1的比例划分内存。

新的对象先进入eden区,eden区垃圾回收得很活跃,当经历几次回收后,如果对象依然存活,则复制到survivor1区,servivor1区也会有垃圾回收,但是频率没有eden区高,当survivor1区容量满了之后,survivor1中存活得对象复制到survivor2中。如此往复,直到survivor1区放不下对象,则将servivor存活的对象放到老年代。老年代中空间满之后,则进行FULL GC。新生代和老年代都装不下的大对象,则直接进入永久代。永久代都装不下的大对象,就会抛出永久代内存溢出的错误。所以一个大的查询语句就可以把内存玩崩。

新生代算法:minor GC (镜像GC?复制?)

老年代算法:标记-整理算法

永久代:永久代主要用于存放静态文件,如JAVA的类和方法。

回收方法:可达性分析算法(GCRoots)回收废弃的变量。

无用的类回收:该类所有实例已经被回收,加载该类的classloader被回收,该类的class对象没有被任何地方引用和反射。

附上:元空间和持久代(永久代)的区别: https://blog.csdn.net/u011531613/article/details/62971713

元空间:最小的数据单元,放在内存中

持久代:放在JVM中。

7,GC 的两种类型:Scavenge GC 和FULL GC

当新对象在eden区申请内存空间失败时,触发Scavenge GC。清除eden区存活对象并转移到Survivor区中,然后整理Survivor的两个区。

FULL GC:

1,老年代空间满了触发

2,持久代被写满

3,持久代内存动态调整:比如,设置的持久代空间为1024M-2048M。那么当持久代达到1024时,触发扩容策略,进行FULL GC

4,主动调用GC。

8,强引用,软引用,弱引用,虚幻引用:https://www.cnblogs.com/fengbs/p/7019687.html

强引用:大致是只要还有引用关系,就不会被回收。Object obj = new Object()

软引用:内存溢出前,回收软引用 

SoftReference<String> softRef=new SoftReference<String>(str);

弱引用:生命周期是下一次垃圾回收之前  WeakReference<String> weakRef = new WeakReference<String>(str);

虚幻引用:作用就是能在这个对象被收集器回收时收到一个系统通知

9,按线程划分算法

串行:

使用单线程执行回收算法,但是无法使用多线程的核心,会stop the world

 

并行

使用多个cpu线程并行执行垃圾回收,效率更高,但是还是会stop the world

并发

实时并发地回收,不影响用户。

新生代:串行垃圾回收器,ParNew收集器(复制),Parellel收集器(复制)

老年代:ParNew收集器(标记-压缩),Parellel 收集器(标记-压缩),Parallel Old 收集器,CMS,G1收集器

原文地址:https://www.cnblogs.com/stanmao/p/10841944.html