垃圾收集器与内存分配策略(一)

2018-03-31  本文已影响0人  jqdywolf

垃圾收集器与内存分配策略之--对象已死吗

GC关注的问题其实就是三个:

所有的GC问题都是关于这三点的描述。
对于JVM来说,首先线程独有的三块(程序计数器、栈、本地方法栈)都是随着线程的开始而创建,线程结束而消亡,一个栈帧在开始时内存已经固定,所以GC没必要处理这部分内存。我们所说的GC都是针对堆和方法区而言的。

对象已死吗

如何判断一个对象已死?一般主流两种方法:引用计数法和可达性分析法

引用计数法

很简单,每个对象维护一个引用计数器,当某个引用指向这个对象时,就让这个引用计数器加1。当一个对象的引用计数器为0,说明对象已死。
致命的缺点:
不好解决循环引用问题。

可达性分析法

通过一组“GC Root”的对象作为起始点,向下搜索,走过的路径上的每个对象是还活着的。不可达的对象就是死的。HotSpot用的就是这个方法。
Java中可被作为GC Root的对象有四种:

再谈引用

一般我们说的引用都是指强引用。

Object obj = new Object();//obj就是一个强引用

而Java中引入一些“弱”的引用。目的为了引入一种这样的对象:当内存足够时,对象保留内存中,当内存不够时,这些对象可被回收。
Java里引用分为四种:强引用、软引用、弱引用、虚引用。引用强度逐渐减弱。
这四种引用的区别就是指向的对象的生存时间不一样。

SoftReference<String> s = new SoftReference<String>(new String("123"));
WeakReference<String> w = new WeakReference<String>(new String("234"));
ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
PhantomReference<String> p = new PhantomReference<>(new String("434"), referenceQueue);//当对象被回收时,referenceQueue就会受到一个消息

一般软引用和弱引用都用于本地缓存中,每次用时判断一下是否被回收,如果被回收再去到数据库里捞。

SoftReference<String> s = new SoftReference<String>(new String("123"));
if (null == s.get()) {//如果已被回收
    //到数据库里捞
}else {//如果没被回收
    System.out.println(s.get());//直接使用
}

生存还是死亡

一个对象GC Root不可达并不代表着立刻死亡。一个对象的死亡要经历两次标记。
具体过程如下:


对象死亡过程

回收方法区

回收方法区的性价比很低,且Java虚拟机规范中并没有强制要求要回收方法区。
回头方法区主要回收两点:常量和无用的类。

上一篇下一篇

猜你喜欢

热点阅读