先说一些题外话,Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区,这些区分为线程私有区和线程共享区

  1、线程私有区

    a、程序计数器

    记录正在执行的虚拟机字节码指令地址。此区域是是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

   b、Java虚拟机栈

    描述的是Java方法执行的内存模型,每个方法在执行的同时会创建一个栈帧

   c、本地方法栈

    它与虚拟机栈发挥的作用是类似的,它们之间的区别不过是虚拟机栈为虚拟机执行java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用的Native方法服务。

  2、线程共享区

   a、Java堆

    被所有线程共享的一块内存区域,也是Java虚拟机所管理的内存中最大的一块。

   b、方法区

    用于存储已被虚拟机加载的类信息、常量、静态变量、即时编辑器编译后的代码等数据,虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名Non-Heap(非堆)

  下面开始说正题

  目前虚拟机基本都是采用可达性算法,为什么不采用引用计数算法呢?下面就说说引用计数法是如何统计所有对象的引用计数的,再对比分析可达性算法是如何解决引用技术算法的不足。先简单说说这两个算法:

  1、引用计数法(reference-counting):每个对象都有一个引用计数器,当对象被引用一次,计数器就加1,当对象引用时效一次就减,当计数器为0,意味着对象是垃圾对象,可以被GC回收。

  2、可达性算法(GC Root Tracing):从GC Root作为起点开始搜索,那么整个连通图中对象都是活的,对于GC Root无法达到的对象便是垃圾对象,随时可被GC回收。

  采用引用计数算法的系统只需在每个实例对象创建之初,通过计数器来记录所有的引用次数即可。而可达性算法,则需要再次GC时,遍历整个GC根节点来判断是否回收。

  下面通过一段代码来对比说明:

  

 public class GcDemo {

    public static void main(String[] args) {
//分为6个步骤
GcObject obj1 = new GcObject(); //Step 1
GcObject obj2 = new GcObject(); //Step 2 obj1.instance = obj2; //Step 3
obj2.instance = obj1; //Step 4 obj1 = null; //Step 5
obj2 = null; //Step 6
}
} class GcObject{
public Object instance = null;
}

  1、引用计数算法

  如果采用的是引用计数算法:

  再回到前面代码GcDemo的main方法共分为6个步骤:

  • Step1:GcObject实例1的引用计数加1,实例1的引用计数=1;
  • Step2:GcObject实例2的引用计数加1,实例2的引用计数=1;
  • Step3:GcObject实例2的引用计数再加1,实例2的引用计数=2;
  • Step4:GcObject实例1的引用计数再加1,实例1的引用计数=2;

  执行到Step 4,则GcObject实例1和实例2的引用计数都等于2。

  接下来继续结果图:
  

  • Step5:栈帧中obj1不再指向Java堆,GcObject实例1的引用计数减1,结果为1;
  • Step6:栈帧中obj2不再指向Java堆,GcObject实例2的引用计数减1,结果为1。

  到此,发现GcObject实例1和实例2的计数引用都不为0,那么如果采用的引用计数算法的话,那么这两个实例所占的内存将得不到释放,这便产生了内存泄露。

  

  2、可达性算法

  这是目前主流的虚拟机都是采用GC Roots Tracing算法,比如Sun的Hotspot虚拟机便是采用该算法。 该算法的核心算法是从GC Roots对象作为起始点,利用数学中图论知识,图中可达对象便是存活对象,

  而不可达对象则是需要回收的垃圾内存。这里涉及两个概念,一是GC Roots,一是可达性。

  那么可以作为GC Roots的对象(见下图):

  • 虚拟机栈的栈帧的局部变量表所引用的对象;
  • 本地方法栈的JNI所引用的对象;
  • 方法区的静态变量和常量所引用的对象;

  关于可达性的对象,便是能与GC Roots构成连通图的对象,如下图:
  

  从上图,reference1、reference2、reference3都是GC Roots,可以看出:

  • reference1-> 对象实例1;
  • reference2-> 对象实例2;
  • reference3-> 对象实例4;
  • reference3-> 对象实例4 -> 对象实例6;

  可以得出对象实例1、2、4、6都具有GC Roots可达性,也就是存活对象,不能被GC回收的对象。
  而对于对象实例3、5直接虽然连通,但并没有任何一个GC Roots与之相连,这便是GC Roots不可达的对象,这就是GC需要回收的垃圾对象。

  到这里,相信大家应该能彻底明白引用计数算法和可达性算法的区别吧。

  再回过头来看看最前面的实例,GcObject实例1和实例2虽然从引用计数虽然都不为0,但从可达性算法来看,都是GC Roots不可达的对象。

  总之,对于对象之间循环引用的情况,引用计数算法,则GC无法回收这两个对象,而可达性算法则可以正确回收。

  参考资料:https://blog.csdn.net/lamp_zy/article/details/53212909

java垃圾回收机制--可达性算法的更多相关文章

  1. 【转载】Java垃圾回收机制

    原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...

  2. Java垃圾回收机制_(转载)

    Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...

  3. 【Java】Java垃圾回收机制

    Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...

  4. Java垃圾回收机制(Garbage Collection)

    引用博客地址:http://www.cnblogs.com/ywl925/p/3925637.html 以下两篇博客综合描述Java垃圾回收机制 第一篇:说的比较多,但是不详细 http://www. ...

  5. Java垃圾回收机制(GC策略)

    Java垃圾回收机制(GC策略) 核心:1,哪些是垃圾?[怎么确定这个是垃圾]:2,如何回收垃圾?[怎么更好收垃圾]. Java语言相对于C++等语言有一个自动垃圾回收机制,只用管使用[实例化对象], ...

  6. 图解Java 垃圾回收机制

    摘要: Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题:给对象分配内存 以及 回收分配给对象的内存,而且这两个问题针对的内存区域就是Java内存模型中的 堆区.关于对象 ...

  7. 【转】深入理解 Java 垃圾回收机制

    深入理解 Java 垃圾回收机制   一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  8. 深入理解java垃圾回收机制

    深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  9. java 垃圾回收机制 引用类型

    Java语言的一个重要特性是引入了自动的内存管理机制,使得开发人员不用自己来管理应用中的内存.C/C++开发人员需要通过malloc/free 和new/delete等函数来显式的分配和释放内存.这对 ...

随机推荐

  1. Java 单例模式的七种写法

    Java 单例模式的七种写法 第一种(懒汉,线程不安全) public class Singleton { private static Singleton instance; private Sin ...

  2. 《java虚拟机》----垃圾收集、内存分配

    No1: 程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操作.每一个栈帧中分配多少内存基本上市在类结构确定下来时就已知的,因 ...

  3. 【WIN10】Bind、Binding與Converter的使用

    Demo源碼下載:http://yunpan.cn/cHuCmI4NK4xwr  访问密码 8201 1.Bind Bind的使用方式是: <Button Content="{x:Bi ...

  4. 【BZOJ 4361】 4361: isn (DP+树状数组+容斥)

    4361: isn Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 218  Solved: 126 Description 给出一个长度为n的序列A( ...

  5. QT学习笔记2:QT中常用函数

    一.QString转number QString number() QString number() QString number() QString number() QString number( ...

  6. BZOJ 2428 JZYZOJ1533 : [HAOI2006]均分数据 模拟退火 随机化

    http://www.lydsy.com/JudgeOnline/problem.php?id=2428 http://172.20.6.3/Problem_Show.asp?id=1533 http ...

  7. Arab Collegiate Programming Contest 2012 J- Math Homework

    思路:由于只有1-6这几个数,而这几个数的最小公倍数是60,所以只需要求出60以内有多少满足条件的数即可. 再就是求出对于给定的n,求出60的倍数.然后就是怎样求的问题了. 首先可以写成如下形式:   ...

  8. hdu 3572 资源分配

    资源分配,每个时间点有m个机器可用,要将这资源分配给n个任务中的一些,要求每个任务在自己的时间范围中被分配了p[i]个资源,建图: 建立源,与每个时间点连边,容量为m,每个任务向其对应的时间段中的每个 ...

  9. python开发_python日期操作

    在python中对日期进行操作的库有: import datetime import time 对日期格式化信息,可以参考官方API: time.strftime datetime 下面是我做的dem ...

  10. [转]基础总结篇之一:Activity生命周期

      子曰:溫故而知新,可以為師矣.<論語> 学习技术也一样,对于技术文档或者经典的技术书籍来说,指望看一遍就完全掌握,那基本不大可能,所以我们需要经常回过头再仔细研读几遍,以领悟到作者的思 ...