JVM——垃圾收集器与内存分配策略(三)

对于垃圾收回我们主要关注3件事情:
1.哪些内存需要回收?
2.什么时候回收?
3.如何回收?
在java内存运行时区域的各个部分,其中程序计数器、虚拟机栈、本地方法栈这3个区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而有条不紊地执行这入栈和出栈,每一个栈帧中分配多少内存基本在类结构确定下来时就已知的,因此在这一个区域的内存分配和回收都具备确定性,不需要过多考虑回收的问题。
而java堆和元空间则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样,我们只有在程序处于期间才能直到会创建哪些对象,这部分内存的分配和回收都是动态的,垃圾收集器所关注的时这部分内存。

1、判定对象是否“存活”

判定对象是否“存活”的两种算法:

1.1、引用计数算法

引用计数法:给对象中添加一个引用计数器,每当由一个地方引用它时,计数器就加一,引用失效时,就减一。当计数器为零时就是不可能再被使用的。这种方法实现简单,判定效率高。但是当两个对象之间互相引用时,导致它们的计数器都不为零,于是引用计数算法无法通知GC收集器回收它们。

1.2、可达性分析算法

这个算法的基本思路就是通过一系列被称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。如下:
在这里插入图片描述
在java中,可作为GC Roots的对象包括下面几种:
1.虚拟机栈(栈帧中的本地变量表)中引用的对象。
2.元空间中类静态属性引用的对象。
3.元空间中常量引用的对象。
4.本地方法栈中JNI(即一般说Native方法)引用的对象。

1.2.1、对象的引用

在java中可以将对于的引用分为下列四种:
1.强引用:就是指在程序代码中普遍存在的,类似“Object obj = new Object()”这类的引用,只要强引用还在,垃圾收集器永远不会回收掉被引用的对象。
2.软引用:用来描述一些由于但非必须的对象。对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。
3.弱引用:弱引用也是描述非必须对象的,但是被弱引用关联到的对象只能生存到下一次垃圾回收发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉被弱引用关联的对象。
4.虚引用:一个对象是否由虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被垃圾收集器回收时收到一个系统通知。

1.2.2、对象生存还是死亡

即使在可达性分析算法中不可达的对象,也并非是“非死不可”,要真正宣告一个对象死亡,至少需要经历两次标记过程。如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那将会被第一次标记并且进行一次筛选。条件就是对象是否由必要执行finalize()方法,当对象没有覆盖此方法或已经被调用过一次了,那虚拟机将视为“没有必要执行”。
如果这个对象被判定由必要执行finalize()方法,那么对象将会放置在一个叫做F-Queue的队列中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里的执行是指虚拟机会触发这个方法,但不承诺会等待它运行结束。因为如果一个对象在finalize()方法中执行缓慢,或者发生死循环等,将很可能导致F-Queue队列中其他对象永久处于等待,严重时会导致内存回收系统崩溃。finalize()方法是对象逃脱死亡的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果这个时候重新与引用链上的任何一个对象建立连接,那么第二次标记时它将被移出“即将回收”的集合,否则,基本上它就真的被回收了。

1.2.3、回收元空间

元空间的垃圾回收主要回收两部分:废弃常量和无用的类。
回收常量与回收java堆中的对象非常相似,就是判断其他地方是否引用了这个常量。
判定一个常量是否“废弃常量”比较简单,但是判定一个类是否是“无用的类”则比较苛刻,需要同时满足3个条件才算是“无用的类”:
1.该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
2.加载该类的ClassLoader已经被回收。
3.该类对应的java.lang.Class对象没有在任何地方引用,无法在任何地方通过反射访问到该类的方法。
虚拟机可以对满足上述3个条件的无用类进行回收,这里是可以,并不是和对象一样,不使用了必然会被回收。是否对类进行回收,HotSpot虚拟机提供了-Xnoclassgc参数进行控制,还可以使用-verbose:class以及-XX:+TraceClassLoading、-XX:+TraceClassUnloading查看类加载和卸载信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值