自动垃圾回收是Java相较于C++的一个重要的特点,想了解JVM的垃圾回收机制,首先我们要知道垃圾回收是回收什么地方的垃圾,我在我的上一篇博客《JVM内存区域划分》里面有写到JVM里面的内存是怎么分布的,这里的回收主要是指对上文中提到的Java堆和方法区的内存的回收。

什么样的对象可以被回收

知道了回收哪里的内存之后,我们还需要知道什么样的对象是可以被回收,或者说是需要被回收的,这些对象我们称之为死掉的对象。那么哪些对象是死掉了的呢?我们说当一个对象不存在任何引用的时候就可以说这个对象是死掉了。

那么什么时候这个对象不存在任何引用了呢?

有一些地方说,可以使用引用计数算法来判断对象是否还存活,引用计数算法是说给对象添加一个引用计数器,每当一个地方引用它时就加1,引用失效时就减1,计数器的值变为0就说这个对象不存在任何引用了,但是这样会存在一个很严重的问题,就是循环引用的问题。比如如下的例子:

public class Example{
public Object instance = null; public static void test(){
Example objA=new Example();
Example objB=new Example(); objA.instance=objB;
objB.instance=objA; objA=null;
objB=null;
}
}

这样的话,objA和objB的引用计数都不为0,但是他们的确是不会再被使用的了。

那么Java里面是用什么样的算法来实现对引用的判断的呢?

Java里是使用可达性分析的方法来实现的。

如图所示,就是通过一系列的称为"GC Roots"的对象作为起始点,从这些点向下搜索,搜索的路径称为引用链,当一个对象到达GC Roots没有任何引用链时,就可以证明这个对象是不可用的。那么这个对象就可以被回收了。像图中的Obj1-5都属于存活的对象,但是Obj6-8虽然还存在相互引用,但是已经是可以认为是死掉的对象了。

引用

目前来说,Java中的引用可以分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)四种,他们的引用顺序依次逐渐减弱。

  • 强引用是用来描述必须存在和引用的对象,比如Object a=new Object(),只要强引用还存在,被引用的对象就永远不会被回收。
  • 软引用是用来描述一些还有用但是不是必需的对象。这类引用的对象会在内存溢出之前被列入回收范围进行第二次回收,如若回收完之后还没有获得足够的内存才会抛出内存溢出异常。可以使用SoftReference类来实现。
  • 弱引用是用来描述非必需的对象,但是强度比软引用更弱,被引用的对象只能存活到下一次GC之前。当进行GC的时候不论内存是否足够都会对该引用的对象进行回收。可以使用WeakReference类来实现。
  • 虚引用是最弱的引用关系。虚引用的存在不会对对象的存活造成任何影响,也不能通过虚引用来获得任何对象实例。设置虚引用的唯一目的就是在关联对象被回收时会获得一个系统通知。可以使用PhantomReference类来实现。

死亡对象的自我救赎

当一个对象在进行可达性分析的时候发现已经是没有任何引用的了,这时候垃圾收集器并没有立即判处该对象死刑,而是给了它一次自我救赎的机会,这时它会被标记一次,同时判断是不是有必要执行finalize()方法,当对象没有重写finalize()方法或者finalize()方法已经被执行过的时候,就不执行finalize()方法。下面就会有两种情况发生了:

  • 执行finalize()方法:这时这个对象会被放在F-Queue队列之中,然后由虚拟机自动创建一个低优先级的Finalizer线程去执行它,但是为了保证F-Queue不被无限阻塞并不保证一定会等待finalize()方法执行结束。此时在finalize()里如果对象又重新获得与GC Roots的联系就可以完成自我救赎,否则的话就只能被第二次标记,然后听天由命了。
  • 不执行finalize()方法:这时候要么是垃圾收集器已经给过一次机会了,要么是对象自己没有重写finalize()去获得机会,这个时候就只能被第二次标记,立即被执行死刑了。

方法区的回收

方法区的回收分为废弃常量的回收和无用类的卸载。

  • 废弃常量的回收:回收废弃常量与上面所说的堆中对象的回收差不多,没有任何引用的时候回收。
  • 无用类的卸载:类的卸载需要满足三个条件:
  1. 该类的所有对象都被回收。
  2. 加载该类的ClassLoader已经被回收。
  3. 该类对应的java.lang.Class没有在任何地方被引用,无法在任何地方通过反射访问该类。

    但是满足这三个条件只是说可以被回收,但是不代表一定被回收,具体是否被回收还要由虚拟机里的一些参数来具体确定。

JVM内存回收对象及引用分析的更多相关文章

  1. JVM内存回收机制简述

    JVM内存回收机制涉及的知识点太多了,了解越多越迷糊,汗一个,这里仅简单做个笔记,主要参考<深入理解Java虚拟机:JVM高级特性与最佳实践(第二版)> 目前java的jdk默认虚拟机为H ...

  2. JVM内存回收机制——哪些内存需要被回收(JVM学习系列2)

    上一篇文章中讨论了Java内存运行时的各个区域,其中程序计数器.虚拟机栈.本地方法栈随线程生灭,且创建时需要多少内存,基本上在译期间就决定的了,所以在内存回收时无需特殊的关注.而堆和方法区则不同,首先 ...

  3. Java基础-JVM内存回收

    Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:把对象分为年青代(Young).年老代(Tenured).持久代(Perm),对不同生命周期的对象使用不同的算法.( ...

  4. JVM内存回收机制

    1. JVM内存回收机制简述 http://www.cnblogs.com/lzrabbit/p/3826738.html

  5. K8S(18)容器环境下资源限制与jvm内存回收

    K8S(18)容器环境下资源限制与jvm内存回收 目录 K8S(18)容器环境下资源限制与jvm内存回收 一.k8s中的java资源限制与可能的问题 方案1:通过JVM的Xms和Xmx参数限制 方案2 ...

  6. JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程

    此文已由作者赵计刚薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 注意:本文主要参考自<深入理解Java虚拟机(第二版)> 说明:查看本文之前,推荐先知道JVM ...

  7. 第三章 JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程

    注意:本文主要参考自<深入理解Java虚拟机(第二版)> 说明:查看本文之前,推荐先知道JVM内存结构,见<第一章 JVM内存结构> 1.内存回收的区域 堆:这是GC的主要区域 ...

  8. JVM垃圾收集器&对象的引用回收

    1.介绍垃圾收集器 垃圾收集器(Garbage Collection,GC)就是用于回收方法区和堆区,其他程序计数器.虚拟机栈.本地方法栈这3个区域都是随线程而生,随线程而灭,栈中的栈帧会随着方法的进 ...

  9. JVM内存状况查看方法和分析工具

    Java本身提供了多种丰富的方法和工具来帮助开发人员查看和分析GC及JVM内存的状况,同时开源界和商业界也有一些工具可用于查看.分析GC及JVM内存的状况.通过这些分析,可以排查程序中内存泄露的问题及 ...

随机推荐

  1. 利用iframe实现提交表单是页面部分刷新

    直接上代码: <%@ page language="java" import="java.util.*" pageEncoding="utf-8 ...

  2. 你好,C++(8)如何表达那些始终保持不变的数据量?3.2.2 常量

    3.2.2  常量 与变量可以用在程序中表达那些可能会发生变化的数据量相对应地,在C++中,我们用常量来表达那些始终保持不变的数据量.简单来讲,就是程序中直接使用的数值.字符.字符串以及const关键 ...

  3. chrome扩展,如何阻止浏览自动关闭桌面通知.

    (!!!!以前的好用的, 现在不行了~) 做chrome扩展桌面通知, 可能不想让浏览器自动关闭某个重要的桌面通知.那就不要使用 chrome.notifications.create 可以用 Web ...

  4. CentOS6.5安装LAMP环境的前期准备

    首先需要按照前一篇<CentOS 6.5下安装MySql 5.7>的安装步骤配置好防火墙.关闭 SELINUX 1.编译安装libxml2注:libxml2是一个xml的c语言版的解析器, ...

  5. 用webclient.DownloadFile下载exe文件时大小为0

    用自己写的下载软件从服务器端下载文件,别的文件能下,但exe文件显示下载文件大小为0,连接超时,原因是服务上发布的下载文件夹的虚拟目录的属性有问题, 包含.exe 文件的虚拟目录已启用执行应用程序权限 ...

  6. Asp.Net Mvc: 浅析TempData机制(转发 作者: Tristan G )

    Asp.Net Mvc: 浅析TempData机制 环境: Windows 2008, VS 2008 SP1, Asp.Net Mvc 1.0 --------------------------- ...

  7. Tomcat基础教程(三)

    Tomcat中的Web应用 Web应用就是具有特定目录结构的目录和文件. 基于JAVA技术开发的Web应用中通常会包含以下的web对象: 静态文件对象:HTML页面,图片,普通文件 Servlet: ...

  8. SQL中 WHERE与HAVING的区别

    SQL语句中的Having子句与where子句之区别 在说区别之前,得先介绍GROUP BY这个子句,而在说GROUP子句前,又得先说说“聚合函数”——SQL语言中一种特殊的函数.例如SUM, COU ...

  9. Spring中使用log4j随笔

    web.xml中的配置: <!--由Sprng载入的log4j配置文件位置--> <context-param> <param-name>log4jConfigLo ...

  10. Android应用开发学习笔记之AsyncTask

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在上一篇文章中我们学习了多线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作 ...