【Java学习笔记】初步学习JAVA垃圾回收机制

该文章是观看https://www.bilibili.com/video/BV1L7411N77n?p=83视频的学习笔记。

垃圾回收过程主要分为两步:

1.发现无用的对象

2.回收无用对象占用的内存空间。

常见的两种垃圾回收算法:

1.引用计数法

对中农每个对象都有一个引用计数,被引用一次,计数加1,被引用变量值为null,则计数减1,知道计数为0,则表示变成无用对象。优点是算法简单,缺点是:“循环引用的无用对象”无法被识别。

2.可达性分析法

程序把引用的对象都做成一张图。从一个节点开始。寻找对应引用节点,找到这个节点以后,继续寻找这个节点的引用节点。当所有引用节点寻找完毕之后,剩余的节点则被人认为是没有被引用的节点,即无用的节点。

通用的分代垃圾回收机制:

JVM将对象分为年轻代、年老代和永久代;并将内存划分为Eden、Survivor和Tenured/Old三种空间。

年轻代:

里面划分了Eden和Survivor两个区域,年轻代的目的是快速收集掉那些生命周期短的对象。所有新生成的对象都放在Eden区。如:

1.Eden区存满了之后,Minor GC会清空Eden的无用对象,把剩下没结束的对象放入到Survivor1区,新创建的对象又放入到Eden区。

2.接着重复多次第1步操作后,Survivor1区也满了,Minor GC会清空Survivor1区的无用对象,把剩下的放入到Survivor2区。

3.重复多次上述操作等到Survivor2区也满了,Minor GC会清空Survivor2区的无用对象,把剩下的放回到Survivor1区,然后,这时发现,Survivor1区也满了。而Minor GC也发现Survivor区里剩余的都是生存周期很长的对象。便会将这些多处的对象放入到年老代。

注意:三个区之间的对象替换采用的是效率较高的复制算法。例如:Survivor1区满执行了GC之后,将剩余的所有对象直接复制到Survivor2区。

【Java学习笔记】初步学习JAVA垃圾回收机制_第1张图片

年老代: 

负责管理年老代的是Major GC,因为年老代的空间比年轻代大,所以启动Major GC耗费的资源大于Minor GC。年老代里面都是一些声明周期较长的对象。当年老代里面的对象过多时,就会启动Major GC和Full GC全面清理年轻代和年老代区域。

永久代:

用于存放静态文件。如Java类、方法等。持久代对垃圾回收没有显著影响。永久代在JDK7以前就是“方法区”的一种实现。JDK8以后没有“永久代”了,使用netspace元数据空间和堆替代。

Minor GC:用于清理年轻代区域。Eden区满了之后就会触发一次Minor GC。清理无用对象,将有用对象复制到Survivor1、Survivor2等区域中。

Major GC:用于清理年老代区域。

Full GC:用于清理年轻代和年老代区域,成本较高,影响系统性能。

JVM调优和Full GC:

在对JVM调优的过程中,很大一部分工作就是对于Full GC的调节。下面这几种原因会导致Full GC:

1.年老代(Tenured)被写满。

2.永久代被写满。

3.System.go()被显示调用,注:这句代码只是向JVM提出调用Full GC的建议,不是立刻调用

4.上一次GC之后堆(Heap)的各个区域分配策略动态变化。

开发中容易造成内存泄漏的操作:

1.创建大量无用的对象。如:在需要大量拼接字符串时,使用了String而不是StringBuffer。

【Java学习笔记】初步学习JAVA垃圾回收机制_第2张图片

2.静态集合类的使用:像HashMap、Vector、List等的使用最容易出现内存泄漏,这些静态变量的生命周期和应用程序一直。所有对象Object也不能被释放。

3.各种连接对象(IO对象流,数据库连接对象,网络连接对象)未关闭

4.监听器的使用:释放对象时,没有删除对应的监听器。

你可能感兴趣的:(Java学习笔记)