版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习!

在堆内存中存放着Java程序中几乎所有的对象实例,堆内存的容量是有限的,Java虚拟机会对堆内存进行管理,回收已经“死去”的对象(即不可能再被任何途径使用的对象),释放内存。垃圾收集器在对堆内存进行回收前,首先要做的第一件事就是确定这些对象中哪些还存活着,哪些已经死去。Java虚拟机是如何判断对象是否可以被回收的呢?

引用计数算法

       引用计数算法的原理是这样的:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;在任何时刻计数器的值为0的对象就是不可能再被使用的,也就是可被回收的对象。

引用计数算法的效率很高,但是主流的JVM并没有选用这种算法来判定可回收对象,因为它有一个致命的缺陷,那就是它无法解决对象之间相互循环引用的的问题,对于循环引用的对象它无法进行回收。

假设有这样一段代码:

public class Object {

    public Object instance;

    public static void main(String[] args) {

        //
Object objectA = new Object();
Object objectB = new Object(); //
objectA.instance = objectB;
objectB.instance = objectA; //
objectA = null;
objectB = null; }

程序启动后,objectA和objectB两个对象被创建并在堆中分配内存,这两个对象都相互持有对方的引用,除此之外,这两个对象再无任何其他引用,实际上这两个对象已经不可能再被访问(引用被置空,无法访问),但是它们因为相互引用着对方,导致它们的引用计数器都不为0,于是引用计数算法无法通知GC收集器回收它们。

实际上,当第1步执行时,两个对象的引用计数器值都为1;当第2步执行时,两个对象的引用计数器都为2;当第3步执行时,二者都清为空值,引用计数器值都变为1。根据引用计数算法的思想,值不为0的对象被认为是存活的,不会被回收;而事实上这两个对象已经不可能再被访问了,应该被回收。

可达性分析算法

       在主流的JVM实现中,都是通过可达性分析算法来判定对象是否存活的。可达性分析算法的基本思想是:通过一系列被称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots对象没有任何引用链相连,就认为GC Roots到这个对象是不可达的,判定此对象为不可用对象,可以被回收。

在上图中,objectA、objectB、objectC是可达的,不会被回收;objectD、objectE虽然有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

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

1、虚拟机栈中引用的对象;

2、方法区中类静态属性引用的对象;

3、方法区中常量引用的对象;

4、本地方法栈中Native方法引用的对象。

以上探讨了判定对象是否可回收的两种算法,判定对象是否可回收只是垃圾回收的第一步,接下来还要解决何时回收以及如何回收的问题,在后面的文章中我们来探讨这些问题。

Java虚拟机:如何判定哪些对象可回收?的更多相关文章

  1. (转)《深入理解java虚拟机》学习笔记3——垃圾回收算法

    Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...

  2. 自制Java虚拟机(四)-对象、new、invokespecial

    自制Java虚拟机(四)-对象.new.invokespecial 一.对象的表示 刚开始学Java的时候,图书馆各种教程,书名往往都是“Java面向对象高级编程”,通常作者都会与C++做个比较,列出 ...

  3. 深入理解java虚拟机(三)对象回收判断算法以及死亡过程

    在堆里面存放着Java几乎所有的对象实例,垃圾收集器要进行垃圾回收,要做的第一步便是找出那些对象是需要回收的. 怎么判断对象是否需要回收? 常用的方法有两种. 1.引用计数算法.为每一个对象添加一个引 ...

  4. 《深入理解Java虚拟机》学习笔记之内存回收

    垃圾收集(Garbage Collection,GC)并不是Java语言的半生产物,事实上GC历史远比Java久远,真正使用内存动态分配和垃圾收集技术的语言是诞生于1960年的Lisp语言.经过半个世 ...

  5. 深入理解JAVA虚拟机之JVM性能篇---垃圾回收

    一.基本垃圾回收算法 1. 判断对象是否需要回收的方法(如何判断垃圾): 1) 引用计数(Reference Counting)  对象增加一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回 ...

  6. 《深入理解Java虚拟机》读书笔记2--垃圾回收

    回收哪些内存/对象 引用计数算法 可达性分析算法 finalize()方法 HotSpot实现分析 转载:http://blog.csdn.net/tjiyu/article/details/5398 ...

  7. 《深入理解Java虚拟机》读书笔记3--垃圾回收算法

    转载:http://blog.csdn.net/tjiyu/article/details/53983064 下面先来了解Java虚拟机垃圾回收的几种常见算法:标记-清除算法.复制算法.标记-整理算法 ...

  8. 转!!Java虚拟机堆的内存分配和回收

    Java内存分配和回收,主要就是指java堆的内存分配和回收.java堆一般分为2个大的区域,一块是新生代,一块是老年代.在新生代中又划分了3块区域,一块eden区域,两块surviver区域.一般称 ...

  9. 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位

    参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...

随机推荐

  1. Maven测试篇

     maven的生命周期: 讲解Maven测试篇之前将首先介绍一下Maven生命周期的相关概念,如果你熟知这部分概念可以略过此小节内容. 大多数时候,我们在构建一个项目时,不外乎是对其进行清理.编译.测 ...

  2. Warning: session_start() [function.session-start]: Cannot send session cache limiter

    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers alrea ...

  3. 原生js实现图片网格式渐显、渐隐效果

    写正文前先吐槽一下:端午放假完第一天去某千人以上公司面试前端工程师,第一轮是我应聘职位的部门小领导,谈的不错,面试主要围绕要用到的技术来:第二轮来了我要说的正主,我了个去,问的问题一个和前端无关,问我 ...

  4. 使用windows 命令行执行Git clone时出现Host key error

    由于是在java中执行cmd命令调用git clone,导致git读取不到用户的ssh key,需要设置环境变量Home为正确的用户路径: cmd /c set HOME=C:/Users/你的用户名 ...

  5. 通过wireshark学习Traceroute命令(UDP,ICMP协议)

    traceroute: 通过TTL限定的ICMP/UDP/TCP侦测包来发现从本地主机到远端目标主机之间的第三层转发路径.用来调试网络连接性和路由问题. mtr: traceroute的一个变种,能根 ...

  6. git使用3

    如何使用/学习第三方框架? 优秀的第三方框架都在 github.com 1> 搜索 2> git clone 获得完整版本 $ git clone https://github.com/A ...

  7. iOS项目评估报告

    1.整体项目无分层概念,结构混乱,代码耦合严重. 影响:后期扩展困难,维护困难. 解决方案:1.整体采用mvc模式. 2.在原来的基础再抽离出业务层 3.业务层按模块管理,合理分层分包. 4.做好共用 ...

  8. MQL语句大全

    mysql sql语句大全 1.说明:创建数据库 CREATE DATABASE database-name 2.说明:删除数据库 drop database dbname 3.说明:备份sql se ...

  9. PHPstrom的Disable Power Save Mode

    1.安装好phpstorm之后 发现代码高亮和函数自动提示都失效了 网上有人说可能是Power save mode的原因开始没找到这个设置在哪 后来在底部面板的信息提示处发现有一条系统消息: 17:0 ...

  10. 常见类——Object

    1.在Java类继承结构中Java.lang.Object类位于顶端   2.如果定义一个Object类没有使用extends关键字声明其父类,则其父类为Java.lang.Object类   3.O ...