转载

3.JVM对象存活判定算法

1.概述

最近通过看书系统的了解了JVM的GC原理,发现之前自己很多地方理解有偏差,不够详细。之前写过一篇JVM垃圾回收机制的文章,写的太乱了不想再后面加了,所以重开一篇。这篇文章主要介绍 基本概念和JVM的对象存活判定

1.1 什么是垃圾回收

JVM会自动给我们分配内存和释放内存,简单来说,jvm释放内存的过程就是垃圾回收。这里需要注意的是:JVM回收的是“垃圾”对象所占用的内存。

1.2 为什么要进行垃圾回收

  • 避免内存溢出、内存泄漏
  • 合理利用内存,防止垃圾对象占用内存

1.3 学习垃圾回收机制的意义

当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节。

2.对象存活判定

2.1 判定方法

2.1.1 引用计数法

原理

给对象添加一个引用计数器,当有一个地方引用该对象时,计数器值加一;当引用失效时,计数器值就减一。当计数器为零时,表示该对象没有在任何地方被引用,则该对象可以判定为可回收对象。

缺陷

无法解决循环引用的问题。当两个对象互相引用时,则永远不会被回收。

2.1.2 可达性算法

在主流语言的主流实现中,都是通过可达性算法来判定对象是否存活。

原理

以被称为“GC Roots”的对象为起点,从这些节点向下搜索,搜索的路径被称为引用链。 当对象没有任何的引用链与“GC ROOTS”相连 ,则该对象则被判定为可回收对象。

如图,对象object 5、object 6、object 7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

3.JVM对象存活判定算法

GC Roots

在java语言中,可作为GC Roots的对象包括下面几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象

3.对象引用

从上面的判定算法可以看出,我们看重的是对象引用。实际上在JVM中,对象引用不仅仅是有或无两种形式。无论是哪种判定对象存活的方法,根本是在判定“引用”是否存在。java有四种引用:强引用、软引用、弱引用和虚引用。

名称 定义 回收情况
强引用 一般使用的引用,比如new出来的对象,即“Object object = new Object()” 在对象没有被根引用链接的时候被回收
软引用 有用但非必须的对象,比如一些缓存对象 系统将要发生内存溢出前 ,才会将这些引用列入回收范围,进行一次回收操作。在这次回收之后,系统仍然还没有足够的内存,才会抛出内存溢出异常
弱引用 用来描述非必须对象,强度低于软引用 只存活到下一次垃圾回收之前 ,当垃圾回收开始,无论内存是否足够,都会回收
虚引用 为一个对象设置虚引用关联的唯一目的就是 能在这个对象被收集器回收时收到一条系统通知 一个对象有无虚引用,不影响他生存时间;通过一个虚引用也无法获取一个对象实例

4.对象被回收过程

finalize方法中,可将待回收对象赋值给GC Roots可达的对象引用,从而达到对象再生的目的

3.JVM对象存活判定算法

需要注意的是 ,任何一个对象的finalize()方法都只会被系统自动调用一次,如果对象面临下一次回收,它的finalize()方法不会被再次执行,即对象只能自救一次。

5.方法区回收

这里说的方法区,在hotspot中叫做“永久代”,java虚拟机规范中不要求一定要实现方法区的垃圾回收。原因主要是由于方法区回收的性价比太低。

5.1 方法区垃圾主要内容

5.1.1 废弃常量

以常量池中字面量的回收为例,假如一个字符串"abc"已经进入了常量池中,没有任何String对象引用常量池中的"abc"常量,也没有其他地方引用了这个字面量,这个"abc"常量就会被系统清理出常量池

5.1.2 无用的类

同时满足下面三个条件可以回收:

  • 该类所有的实例都已经被回收,即Java堆中不存在该类的任何实例
  • 加载该类的ClassLoader已经被回收
  • 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法

需要注意的是,这里说的是“可以回收”,而不是一定回收。类的回收和对象的回收不一样的地方就在此。是否对类进行回收,HotSpot虚拟机提供了-Xnoclassgc参数进行控制。

还可以使用-verbose:class以及-XX:+TraceClassLoading、

-XX:+TraceClassUnLoading查看类加载和卸载信息,其中-verbose:class和-XX:+TraceClassLoading可以在Product版的虚拟机中使用,-XX:+TraceClassUnLoading参数需要FastDebug版的虚拟机支持。

原文  https://segmentfault.com/a/1190000022074875
正文到此结束
Loading...