zoukankan      html  css  js  c++  java
  • 哦?原来这就是 JVM 垃圾!

    大家都知道,JVM 有垃圾回收的机制,垃圾回收的前提是要知道:什么是垃圾!然后再是如何识别垃圾

    什么是垃圾

    垃圾,本质上就是没有引用的对象(们),下面来介绍两种垃圾

    1. 没有引用指向的对象

    下图是对象间引用的状态,从正常引用到引用断开,这个 A 和 C 的引用断开之后,C 就成了那个垃圾。
    正常到断开连接

    2. 没有引用指向的一组对象

    一个典型的案例如下图,就是循环引用,这几个对象看起来都有引用指向,但是其实他们只是一堆紧紧相拥的垃圾。
    一堆垃圾

    如何识别垃圾

    上面介绍了什么是垃圾,那要如何才能识别出垃圾呢?主要有两种算法:

    1. 引用计数法
    2. 可达性分析法

    1. 引用计数法

    算法很简单,就是在对象头上加上被引用的次数,对象的被引用的次数为 0 之日,就是其成为垃圾之时!这个算法的优点是垃圾回收及时,只要对象被引用次数为 0,就可以回收了。

    下图是引用计数的示意图,对象 A、B、C 都被引用了一次
    正常引用计数

    如果 A 跟 C 的引用断开,则 C 的引用次数减一,变为 0,此时 C 就是垃圾
    引用计数断开引用

    引用计数法有个致命的缺点:那就是无法识别出循环引用!
    下图是一个循环引用,明明他们就是一堆垃圾,但是因为被引用次数都不为 0,引用计数法无法识别出他们是垃圾。
    引用计数循环引用

    2. 可达性分析法

    引用计数法的缺点过于致命,目前 JVM 采用的是另一种算法来识别垃圾:可达性分析法。

    这个算法的基本思路就是:从一系列根对象(GC Roots)开始,根据引用关系向下搜索,如果某个对象到 GC Roots 间没有任何引用,则证明此对象是不可能再被使用的,也就是垃圾。

    其示意图如下,左边绿色部分的对象,都可以连向 GC Roots,所以他们都是存活的对象。而右边灰色的部分,即使他们是循环引用,他们也跟 GC Roots 之间没有连接路径,所以灰色部分的对象是垃圾。
    可达性分析法
    那么,究竟是哪些对象能成为至高无上的 GC Roots 呢?以下是主要的 GC Roots:

    • 虚拟机中引用的对象,如各个线程调用的方法堆栈中的参数、局部变量等。
    • 方法区中类的静态属性引用的对象,如类的引用类型的静态变量。
    • 方法区中常量引用的对象,如字符串常量池里的引用。
    • 本地方法栈中 JNI(Native 方法)引用的对象。
    • 虚拟机内部的引用,如基本数据类型对应的 Class 对象,一些常驻的异常对象(比如 NullPointExcepitonOutOfMemoryError)等,还有系统类加载器。

    优点:解决引用计数器所不能解决的循环引用问题。
    缺点:

    1. 耗时:因为需要从 GC Roots 开始逐个检查引用;
    2. STW:GC 过程中需要保证对象的引用关系不能发生变化,所以 GC 进行时必须停顿所有执行线程(STW:Stop The World)。

    总结

    第一部分我们介绍了什么是垃圾:没有任何引用指向的一个或多个对象。
    第二部分介绍了如何识别垃圾,有两种算法:

    1. 引用计数法:通过给对象添加被引用的次数来识别。优点是回收简单及时;缺点是无法解决循环引用。
    2. 可达性分析法:从一系列根对象(GC Roots)开始,根据引用关系向下搜索,如果某个对象到 GC Roots 间没有任何引用,则此对象就是垃圾。优点是解决了循环引用;缺点是耗时和 STW。
  • 作者:小新是也
  • 链接:http://www.cnblogs.com/chenchuxin
  • 来源:博客园
  • 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
查看全文
  • 相关阅读:
    java 环境变量配置
    框架分成介绍
    Net 新特性
    一 设计模式六大原则
    web api 配置
    Visual Studio检查内存泄露方法
    深度比较对象的不同
    reportview 安装使用
    Nuget 常用命令
    freeswitch学习笔记
  • 原文地址:https://www.cnblogs.com/chenchuxin/p/15256320.html
  • Copyright © 2011-2022 走看看