堆里面存放着Java世界差点儿全部的对象实例,垃圾收集器在对堆进行回收前。第一件事情就是要确定这些对象之中哪些还存活,哪些已经死去。推断对象的生命周期是否结束有下面几种方法

引用计数法

详细操作是给对象加入一个引用计数器。每当有一个地方引用时。计数器的值就加1,;当引用失效时。计数器就减1。不论什么时刻计数器为0的对象就 是不可能再被使用的。客观的说引用计数器算法实现简单,判定效率也非常高,在大部分情况下他都是一个不错的算法。可是引用计数器有缺陷

举个简单的样例,对象A和对象B都有字段instance,赋值命令objA.instance = objB,objB.instance=objA,除此之外。这两个对象再无不论什么引用,实际上这两个对象已经不可能再被訪问了,可是他们由于互相引用这对方。导致引用数据器不为0,无法通知CG收集器收集他们。

public class ReferenceCountingGC{
public Object instance = null;
private static final int _1MB = 1024*1024;
// 这个成员属性的唯一意义就是占点内存,以便能在GC日志中看清楚是否被回收过
private byte[] bigSize = new byte[2*_1MB];
public static void testGC{
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA; obj.A = null;
obj.B = null;
}
}

通过GC日志。虚拟机并没有由于这两个对象互相引用就不回收他们。这从側面说明虚拟机不是通过引用计数器来推断对象是否存活。

可达性分析算法

这个算法的基本思路是通过一系列称为“GC Roots”的对象作为起始点,从这些节点開始向下搜索。搜索走过的路径称为引用链,当一个对象到GC Roots没有不论什么引用链相连。则证明此对象是不可用的。

Java语言中。可作为GC Roots的对象包括

1、虚拟机栈(栈帧中的本地变量表)中引用的变量

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

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

4、本地方法栈中JNI(Native方法)引用的对象

引用分析

假设reference类型的数据中存储的数值代表的是还有一块内存的起始地址,就称为这块内存代表着一个引用。这样的定义太过狭隘,一个对象在这样的定义下仅仅有被引用和没有被引用两种状态。对于怎样描写叙述一些“食之无味。弃之可惜”的对象就显得无能为力。我们希望能描写叙述这样一类对象,当内存空间足够时。则能够保存在内存之中。假设内存空间在进行垃圾回收后还是非常紧张,则能够抛弃这些对象。

在JDK1.2以后,Java对引用进行了扩展。将引用分为强引用、软引用、弱引用、虚引用四种,强度依次递减。

1、强引用:程序中普遍存在。比如Object obj = new Object();仅仅要强引用来,CG永远不会回收

2、软引用:描写叙述一些还实用,可是并不是必要的对象。

对于软引用的对象。在系统将要发生内存溢出之前,会把这些对象列进回收范围之中进行二次回收,假设回收了还没有足够的内存将报出内存溢出,JDK1.2之后提供了SoftReference类来实现软引用。

3、弱引用:也是描写叙述非必须对象,被弱引用的对象仅仅能生存到下一次垃圾收集之前。当垃圾收集器工作时,不管内存是否够用都会被回收,JDK1.2之后提供了WeakReference类来实现弱引用。

4、虚引用:幽灵引用或者幻影引用,最弱。一个对象是否有虚无引用的存在。全然不会对其生存时间构成影响,也无法通过虚无引用来取得一个对象实例。

生存还是死亡

即使在可达性分析算法中不可达对象,也并不是是“非死不可”的,这时候他们临时出“缓刑”之中,要真正宣告一个对象死亡。至少要经历两次标记过程:假设对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那他会被第一次标记而且进行一次筛查,筛查的条件是此对象是有有必要运行finalize方法。

当对象没有覆盖finalize方法,或者finalize方法已经被虚拟机调用过,虚拟机将这两种情况视为没有必要运行。

类的Finalize方法,能够告诉垃圾回收器应该运行的操作,该方法从Object类继承而来。在从堆中永久删除对象之前。垃圾回收器调用该对象的Finalize方法。注意,无法确切地保证垃圾回收器何时调用该方法,也无法保证调用不同对象的方法的顺序。即使一个对象包括还有一个对象的引用。或者在释放一个对象非常久曾经就释放了还有一个对象,也可能会以随意的顺序调用这两个对象的Finalize方法。假设必须保证採用特定的顺序,则必须提供自己的特有清理方法。

回收方法区

方法区即为Hotspot虚拟机中的永久代,永久代的垃圾收集主要回收两部分内容:废弃常量和没用的类。以常量字符串”abc”为例,已经进入常量池,可是当前系统没有不论什么一个String对象叫做abc,换句话说就是没有不论什么String对象引用常量池中的abc,假设此时发生内存回收,这个abc常量就会被系统清理出常量池。常量池中的其它类、接口、方法、字段的符号引用也与此相似。

判定一个常量是否是废弃常量比較简单,而判定一个类是否是没用的类的条件 要苛刻的多,没用的类要满足下面条件:

1、该类全部的实例都已经被回收,Java堆中不存在该类的不论什么实例。

2、载入该类的ClassLoader已经被回收

3、该类的Java.lang.class对象没有在不论什么地方被引用。无法在不论什么地方通过反射訪问该类。

最新文章

  1. SQL Server中公用表表达式 CTE 递归的生成帮助数据,以及递归的典型应用
  2. 使用Gson解析json
  3. 转:Jmeter之Bean shell使用(二)
  4. AutoGenSystem
  5. ZOJ 3790 Consecutive Blocks (离散化 + 暴力)
  6. 服务器上的iptables
  7. WebView loadData出错(奇怪的设计)
  8. HDU 1151 Air Raid(最小路径覆盖)
  9. hdu 1010 Tempter of the Bone 深搜+剪枝
  10. Codeforces Round #261 (Div. 2)——Pashmak and Buses
  11. Boxes in a Line(移动盒子)
  12. Linux网络中接收 "二进制" 流的那些事 --- 就recv的返回值和strlen库函数进行对话
  13. Struts2与Ajax数据交互
  14. selenium提供的截图功能
  15. vue-cli 构建的项目中 如何使用less
  16. I - Magic FZU - 2280 (字符串hash)
  17. WebStorm中使用npm包管理器
  18. java多线程系列14 设计模式 Master-Worker
  19. [Node.js与数据库]node-mysql 模块介绍
  20. Mac显示器不亮

热门文章

  1. AJAX - 封装AJAX GET 数组join( )方法 键值对取value POST请求参数注意点
  2. 使用Multiplayer Networking做一个简单的多人游戏例子-1/2
  3. JavaBean对象转map
  4. code-代码平台服务器路径
  5. 软件——机器学习与Python,Python3的输出与输入
  6. 利用ServiceWorker实现页面的快速加载和离线访问
  7. Django环境搭建(二)
  8. 14. Spring Boot MyBatis 连接数据库
  9. (转)Oracle RAC日常管理命令
  10. Java ThreadLocal Example(java中的ThreadLocal例子)