《JVM笔记》之二:垃圾收集器与内存分配策略

阅读更多

引用计数算法:

判定一个对象是否还存活,一个比较简单的算法就是引用计数算法。比较著名案例就是微软的COM技术、使用ActionScript 3的FlashPlayer、Python语言以及游戏脚本中的Squirrel都利用这个算法进行内存管理。但是Java中并没有使用这项技术,主要原因是循环引用问题。

 

根搜索算法:

在主流的商用程序语言中,包括Java、C#、Lisp等都使用的是根搜索算法 GC Root Tracing判定对象是否存活。任何对象到GC Roots的路径不可达的时候就认定需要回收了,而不管它们之间的循环引用。

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

* 虚拟机栈(栈帧中的本地变量表)中的引用的对象

* 方法区中的static属性引用的对象

* 方法区中final引用的对象

本地方法栈中JNI的引用的对象

 

Java的引用分为四种,从强到弱依次为:

* 强引用 Strong Reference:

  强引用是程序代码中普遍存在的,类似 Object ojb = new Object()的引用,只要强引用存在,垃圾收集器永远都不会回收掉被引用的对象。

* 软引用 Soft Reference:

  软引用用来描述一些还有用,但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中并进行第二次回收,如果这次回收还是没有足够的内存,才会抛出内存溢出异常。提供了SoftReference类来实现软引用。

* 弱引用 Weak Reference:

  弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。提供了WeakReference类来实现弱引用。

* 虚引用 Phantom Reference

  虚引用也称为幽灵引用或者幻引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是希望这个对象被GC回收时收到一个系统通知。提供PhantomReference类实现虚引用。

 

对象有一个finalize()方法,是对象逃脱死亡命运的最后一次机会,如果对象在finalize将自己赋给任何一个引用链里面的对象相关联,那么又活了。哈哈。 但是所有对象的这个方法只能被系统调用一次,也就是只有一次机会去拯救自己。这个方法最好别用,谢谢。

 

内存回收算法:

1,标记-清除 算法  Mark-Sweep

最基本的算法,效率很低

2,复制算法

将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。回收时,将Eden和Survivor中还存活的对象一次性copy到另一个Survivor空间,然后清理掉Eden和刚用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor比例是8:1. 不够的时候会有分配担保来保证。

3,标记-整理 算法:

跟标记-清除算法类似,只是标记后先让所有存活对象前面移动,然后一次性清理最后的区域。

4,分代收集算法

当代商业虚拟机的垃圾收集都采用分代收集 Generational Collection算法。

新生代中采用复制算法,因为这里面对象更新换代很快。

老年代采用标记-整理 算法。

 

新生代的Minor GC示例:

/**
 * VM参数: -verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:SurvivorRatio=8 -XX:+PrintGCDetails
 * @author Administrator
 *
 */
public class MinorGC {
	private static final int _1MB = 1024 * 1024;
	public static void main(String[] args) {
		byte[] a1, a2, a3, a4;
		a1 = new byte[2 * _1MB];
		a2 = new byte[2 * _1MB];
		a3 = new byte[2 * _1MB];
		a4 = new byte[4 * _1MB]; // 出现一次Minor GC

	}
}

 

本人博客已搬家,新地址为:http://www.pycoding.com/

你可能感兴趣的:(Java,JVM)