我们知道JVM采用可达性分析来进行对象内存回收,但是作为GC Roots的四种对象本身是怎么回收的呢?虚拟机栈和本地方法栈引用的对象可以在栈回收(方法调用结束)之后回收,类静态属性引用对象可以在类回收之后被回收,但是常量引用对象该怎么回收呢?
《深入理解Java虚拟机》中并没有给出比较明确的说法,举了个例子,String对象“abc”,只要系统中没有String对象指向“abc”,就可以在必要的时候回收“abc”。那怎么判断系统中没有“abc”的引用呢?计数算法(如果是这样,那常量池中的引用就一定不会出现循环引用的问题吗)?还是通过别的什么方式呢?
这个主要还是看不同的jvm的实现。计数法这个现在应该不怎么用了,都是判断有没有引用来的。
常量池应该是个类似很大的table,由于有table对其内部字符串的引用致使常亮不会被回收。但如果出现空间紧张的情况我觉得可能使用某些算法,比如lru确认那些不在被外部引用的字符串是不是可以销毁。
“都是判断有没有引用来的“
怎么判断的呢?如果分不同的实现,那在主流jvm实现(hotspot)一般是怎么判断的呢?
@Feng_zhulin:
三个步骤:
1. stop the world
2. 从gc roots开始mark所有可达对象
3. sweep 所有未标记对象
@Daniel Cai: 你还是没有弄明白我问的东西,可以通过GC Rootsmark可达对象,然而GC Roots本身谁来mark呢?它们本身在需要回收的时候要怎么办呢?我在问题中指出了四种GC Roots对象其中的三种该怎么回收,现在疑问的是第四种,方法区中的常量引用对象该如何GC。
GC roots 是一组对象引用,或者说是指针,废弃常量也能通过这些根引用来识别。
您好,最近我也在思考这个问题,请问您现在有什么思路了吗?
你的理解应该有问题,你说的GC ROOTS四个对象,那个也是引用啊。比如栈引用的对象。你的栈退出后这个应用就没有了就不引用了啊,同样的方法区类卸载了常量和静态属性的引用就没有了。你可以理解那四个有一个Root的根。对应的场景消失了,他们也就不引用了,就可以销毁。只是从这个虚拟的Root开始是否可达