判断对象的存活
引用计数法:快,方便,实现简单;缺点:对象相互应用,很难判断对象是否回收
可达性分析
判断对象是否存活的。这个算法的基本思路是通过系列的称为“GC Roots”的对象作为起始点,从这些几点开始向下搜索,搜索所走过的路径称为引用链接(reference Chain),当一个对象GC roots没有任何应用链相连是,则证明此对象是不可用的。
作为GC Roots的对象包括下面几种:
- 虚拟机栈(栈帧中的本地变量表)中引用对象。
- 方法区中的类静态属性引用的对象。
- 方法区中常量引用对象。
- 本地方法栈中JNI(即一般说的Native方法)引用的对象
引用
强引用
- 一般的Object obj = new Object(); 就属于强引用
软引用 SoftReference
- 一些有用但是并非必需,用软引用关联的对象,系统将要发生OMM(内存溢出)之前,这些对象就会被回收。
public static class User{
public int id = 0;
public String name = "";
public User(int id,String name) {
this.id = id;
this.name=name;
}
}
public static void main(String[] args) {
User user = new User(1, "小明");
SoftReference<User> userSoft = new SoftReference<User>(user);
user = null;
System.out.println(userSoft.get());
System.gc();
System.out.println("GC完成后");
System.out.println(userSoft.get());
List<Byte[]> list = new LinkedList<Byte[]>();
try {
for (int i = 0; i < 10000; i++) {
System.out.println("**********"+userSoft.get());
list.add(new Byte[1024*1024*1]);
}
} catch (Throwable e) {
System.out.println("Throwable***********"+userSoft.get());
}
}
运行结果:
[GC (System.gc()) 893K->632K(9728K), 0.0013160 secs]
[Full GC (System.gc()) 632K->569K(9728K), 0.0054084 secs]
GC完成后
com.enjoy.cap1.StackAlloc$User@7852e922
**********com.enjoy.cap1.StackAlloc$User@7852e922
**********com.enjoy.cap1.StackAlloc$User@7852e922
[GC (Allocation Failure) 4670K->4825K(9728K), 0.0002478 secs]
[GC (Allocation Failure) 4825K->4761K(9728K), 0.0003084 secs]
[Full GC (Allocation Failure) 4761K->4665K(9728K), 0.0064745 secs]
[GC (Allocation Failure) 4665K->4665K(9728K), 0.0004925 secs]
[Full GC (Allocation Failure) 4665K->4652K(9728K), 0.0067316 secs]
Throwable***********null
弱引用 WeakReference
一些有用(程度比软引用更低)但是并非必需,用弱引用相关的对象,只能生存到下一次垃圾回收之前,GC发生时,不管内存够不够,都会被回收
public static class User{
public int id = 0;
public String name = "";
public User(int id,String name) {
this.id = id;
this.name=name;
}
}
public static void main(String[] args) {
User user = new User(1, "小明");
WeakReference<User> userSoft = new WeakReference<User>(user);
user = null;
System.out.println(userSoft.get());
System.gc();
System.out.println("GC完成后");
System.out.println(userSoft.get());
}
运行结果:
[GC (System.gc()) 892K->600K(9728K), 0.0006343 secs]
[Full GC (System.gc()) 600K->569K(9728K), 0.0039438 secs]
GC完成后
null
虚应用 PhantomReference
幽灵引用,最弱,被垃圾会后的时候收到一个通知
: 软引用SoftReference和弱引用WeakReference,可以用在内存资源紧张的情况下以及创建不是很重的数据缓存。当系统内存不足的时候,缓存中的内容是可以被释放的。 例如:一个程序用来处理用户提供的图片。如果将所有图片读入内存,这样虽然可以很快的打开图片,但内存空间使用巨大,一些使用较少的图片浪费内存空,需要手动冲内存中移除,如果每次打开图片都是从磁盘文件中读取到内存中再显示出来,虽然内存占用较少,但一些经常使用的图片每次打开都要访问磁盘,代价巨大。这个是偶就是可以用软引用构建对象