关于引用 本帖最后由 cup_t 于 2013-08-28 11:22:34 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 不会的,jvm已经考虑到这种相互引用的情况了 http://blog.csdn.net/sunmenggmail/article/details/8172273这里说不能回收 http://blog.csdn.net/sunmenggmail/article/details/8172273这里说不能回收这种明显的问题,一个正规的商业公司不可能考虑不到的,而且也不是一个不可能解决的问题,现代虚拟机是可以解决这个问题的。请参考:http://hi.baidu.com/71167609/item/8bad8069eba97894c5d249f0 不能回收,内存泄漏。根搜索算法检测到两个对象没有死亡。如果设置a=null;b=null;可以回收。 强引用并不能保证对象不被回收。垃圾回收机制除了检查对象是否被引用外,还要看对象是否被至少一个GC roots对象直接或者间接引用。GC roots对象包括以下一些类容:1 每个线程当前的函数调用栈,从栈顶到栈底的每个函数里的局部变量。2 静态的变量3 被jni中引用到的变量。 所以,上面例子中两个循环引用的对象,虽然都存在一个强引用,但是不被任何GC root对象直接或者间接引用到,垃圾回收机制能够发现这个问题。 另外,为了验证这一点,特意翻看了一下android源码中GC管理这一块的代码。在MarkSweep.c这文件中,有一个void dvmHeapMarkRootSet()函数,这个函数对于GC root对象,有一些详细的说明,有兴趣的可以细看一下。 所以,java对于循环引用有一套自己的解决方案。但是话又说回来,一般实际编码中出现的循环引用不会是上面那个例子那样明显,一般都是多个对象复杂的引用导致的循环,这个时候,如果一个对象的生命周期很长,就会导致多个对象都释放不了,所以还是要特别留意对象之间的引用关系。 循环引用会被回收。JVM从很久以前(可能是1.2)开始就解决了这个问题。这是一个非常基本的问题,一般垃圾回收器都会考虑这个问题(关键词google:jvm circular reference)另外做一个实验吧:package test;public class Test { private Test obj; private String iName; Test(String name) { iName = name; } void setObj(Test o) { obj = o; } @Override public void finalize() { System.out.println("gc!" + iName); } public static void main(final String[] args) throws Exception { for (int i = 0; i < 1000; i++) { Test a = new Test("a"); Test b = new Test("b"); a.setObj(b); b.setObj(a); } System.gc(); Thread.sleep(1000); }}输出:gc!bgc!bgc!bgc!agc!bgc!agc!bgc!bgc!agc!a...以下略 GC root 不可达时可以回收,可达时不能回收。下面的代码不能回收public class Test { private Test obj; private int _10MB = 10 * 1024 * 1024; public byte[] bb = new byte[_10MB]; void setObj(Test o) { obj = o; } public static void main(final String[] args) throws Exception { Test a = new Test(); Test b = new Test(); a.setObj(b); b.setObj(a); System.gc(); Thread.sleep(1000); }} 帮忙分析一下哪些是正确的" is a"关系 关于java输出的问题 急求JAVA绘图,用鼠标激活图形热点,拖动改变大小的方法 关闭模式对话框 JTable 标题栏的问题 sql插入日期出错,拜求各位高手救急!!! 哪位有时间,帮忙写下这个的实现过程,让我参考学习一下(非作业) 请问怎么在MDI窗体中设计事件? 招募k-java程序员(兼职) 一道基础英语填空题(Java) java通过JNI读取注册表信息报错 想做一个小程序,自动在网页上填写东西
这里说不能回收
这里说不能回收
这种明显的问题,一个正规的商业公司不可能考虑不到的,而且也不是一个不可能解决的问题,现代虚拟机是可以解决这个问题的。
请参考:http://hi.baidu.com/71167609/item/8bad8069eba97894c5d249f0
如果设置a=null;b=null;可以回收。
1 每个线程当前的函数调用栈,从栈顶到栈底的每个函数里的局部变量。
2 静态的变量
3 被jni中引用到的变量。
所以,上面例子中两个循环引用的对象,虽然都存在一个强引用,但是不被任何GC root对象直接或者间接引用到,垃圾回收机制能够发现这个问题。
另外,为了验证这一点,特意翻看了一下android源码中GC管理这一块的代码。在MarkSweep.c这文件中,有一个void dvmHeapMarkRootSet()函数,这个函数对于GC root对象,有一些详细的说明,有兴趣的可以细看一下。
所以,java对于循环引用有一套自己的解决方案。但是话又说回来,一般实际编码中出现的循环引用不会是上面那个例子那样明显,一般都是多个对象复杂的引用导致的循环,这个时候,如果一个对象的生命周期很长,就会导致多个对象都释放不了,所以还是要特别留意对象之间的引用关系。
JVM从很久以前(可能是1.2)开始就解决了这个问题。这是一个非常基本的问题,一般垃圾回收器都会考虑这个问题(关键词google:jvm circular reference)另外做一个实验吧:
package test;public class Test {
private Test obj;
private String iName; Test(String name) {
iName = name;
} void setObj(Test o) {
obj = o;
} @Override
public void finalize() {
System.out.println("gc!" + iName);
} public static void main(final String[] args) throws Exception {
for (int i = 0; i < 1000; i++) {
Test a = new Test("a");
Test b = new Test("b");
a.setObj(b);
b.setObj(a);
}
System.gc(); Thread.sleep(1000);
}
}
输出:
gc!b
gc!b
gc!b
gc!a
gc!b
gc!a
gc!b
gc!b
gc!a
gc!a
...以下略
下面的代码不能回收public class Test {
private Test obj;
private int _10MB = 10 * 1024 * 1024;
public byte[] bb = new byte[_10MB];
void setObj(Test o) {
obj = o;
}
public static void main(final String[] args) throws Exception { Test a = new Test();
Test b = new Test();
a.setObj(b);
b.setObj(a); System.gc();
Thread.sleep(1000); }
}