Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Java WeakReference案例会出现OutOfMemoryError?;_Java - Fatal编程技术网

为什么Java WeakReference案例会出现OutOfMemoryError?;

为什么Java WeakReference案例会出现OutOfMemoryError?;,java,Java,我知道弱引用将很容易使用GC。及 弱引用对象,不阻止其引用对象可终结、终结和回收。弱引用通常用于实现规范化映射。 假设垃圾收集器在某个时间点确定某个对象是弱可访问的。届时,它将自动清除对该对象的所有弱引用,以及对任何其他弱可及对象的所有弱引用,通过强引用和软引用链可以从这些弱可及对象中获得该对象。同时,它将声明所有以前弱可达的对象都是可终结的。同时或在稍后的某个时间,它将使那些在引用队列中注册的新清除的弱引用排队 但是,下面的代码将用于OOM //-XX:+HeapDumpOnOutOfMem

我知道弱引用将很容易使用GC。及

弱引用对象,不阻止其引用对象可终结、终结和回收。弱引用通常用于实现规范化映射。 假设垃圾收集器在某个时间点确定某个对象是弱可访问的。届时,它将自动清除对该对象的所有弱引用,以及对任何其他弱可及对象的所有弱引用,通过强引用和软引用链可以从这些弱可及对象中获得该对象。同时,它将声明所有以前弱可达的对象都是可终结的。同时或在稍后的某个时间,它将使那些在引用队列中注册的新清除的弱引用排队

但是,下面的代码将用于OOM

//-XX:+HeapDumpOnOutOfMemoryError -Xmx20m -Xms20m -XX:+PrintGCDetails
@Test(expected = OutOfMemoryError.class)
public void testOne() {
    WeakReference<List<char[]>> holder = new WeakReference<>(Lists.newLinkedList());

    for (int i = 0; i < 20; i++) {
        holder.get().add(new char[_512_KB]);
        System.out.println("i = " + i + "; size = " + holder.get().size());
    }
}

GC被调用。

谢谢@matt<代码>holder.get().add(新字符[_512_KB])导致案例

更好的代码是:

    //-XX:+HeapDumpOnOutOfMemoryError -Xmx20m -Xms20m -XX:+PrintGCDetails
@Test(expected = OutOfMemoryError.class)
public void testOne() {
    WeakReference<List<char[]>> holder = new WeakReference<>(Lists.newLinkedList());

    for (int i = 0; i < 20; i++) {
        char[] chs = new char[_512_KB];
        holder.get().add(chs);
        System.out.println("i = " + i + "; size = " + holder.get().size());
    }
}
/-XX:+heapdumponotofmemoryError-Xmx20m-Xms20m-XX:+PrintGCDetails
@测试(预期为OutOfMemoryError.class)
公共void testOne(){
WeakReference holder=newweakreference(Lists.newLinkedList());
对于(int i=0;i<20;i++){
char[]chs=新字符[_512_KB];
holder.get().add(chs);
System.out.println(“i=“+i+”size=“+holder.get().size());
}
}

好吧,在第一种情况下,您只有一个重复使用的弱引用,因此您填写了一个无法收集的列表(或者如果它将被收集,您将得到一个引用错误)。您的第二个案例使用了两个列表,其中一个可以在迭代过程中根据需要收集。如果您使用了两个列表,那么当您添加到其中一个列表时,内存不足,另一个可以删除。但是,如果只有一个列表,并且在添加到列表的中途,内存不足,则无法删除当前使用的列表,因为您当前正在使用它。因此,没有任何地方可以恢复内存,因此会出现内存不足错误。
holder.get()
您对要调用的列表有很强的引用
add
。在调用add之前,将分配新的char[]。因此,在分配更多内存时,始终有一个强引用。
    //-XX:+HeapDumpOnOutOfMemoryError -Xmx20m -Xms20m -XX:+PrintGCDetails
@Test(expected = OutOfMemoryError.class)
public void testOne() {
    WeakReference<List<char[]>> holder = new WeakReference<>(Lists.newLinkedList());

    for (int i = 0; i < 20; i++) {
        char[] chs = new char[_512_KB];
        holder.get().add(chs);
        System.out.println("i = " + i + "; size = " + holder.get().size());
    }
}