为什么此代码示例会产生内存泄漏?

cit*_*nas 3 java garbage-collection memory-leaks

在大学里,我们得到了以下代码示例,我们被告知,运行此代码时存在内存泄漏.示例应该证明这是垃圾收集器无法工作的情况.

就我的面向对象编程而言,唯一能够创建内存泄漏的代码行就是

items=Arrays.copyOf(items,2 * size+1); 
Run Code Online (Sandbox Code Playgroud)

文件称,这些元素被复制.这是否意味着复制了引用(因此创建了堆上的另一个条目)或者正在复制对象本身?据我所知,Object和因此Object []被实现为引用类型.因此,为"项目"分配新值将允许垃圾收集器发现旧的"项目"不再被引用,因此可以被收集.

在我看来,这个代码示例不会产生内存泄漏.有人可能证明我错了吗?=)

import java.util.Arrays;
public class Foo  
{  
private Object[] items;  
private int size=0;  
private static final int ISIZE=10;

public Foo()  
{  
  items= new Object[ISIZE];  
}  

public void push(final Object o){  
  checkSize();  
  items[size++]=o;  
}  

public Object pop(){  
  if (size==0)  
    throw new ///...  
  return items[--size];  
}  
private void checkSize(){  
  if (items.length==size){  
    items=Arrays.copyOf(items,2 * size+1);  
  }  
}  
}
Run Code Online (Sandbox Code Playgroud)

Len*_*lov 11

pop方法产生内存泄漏.

原因是您只减少了队列中的项目数,但实际上并没有将它们从队列中删除.引用仍保留在数组中.如果不删除它们,垃圾收集器将不会破坏对象,即使执行生成该对象的代码也是如此.

想象一下:

{
    Object o = new Object();
    myQueue.add(o);
}
Run Code Online (Sandbox Code Playgroud)

现在,您只有一个此对象的引用 - 数组中的一个引用.

你以后做:

{
    myQueue.pop();
}
Run Code Online (Sandbox Code Playgroud)

此弹出窗口不会删除引用.如果不删除引用,垃圾收集器会认为您仍在考虑使用此引用,并且此对象很有用.

因此,如果您使用n多个对象填充Queue,那么您将保留对这些n对象的引用.

这是老师告诉你的内存泄漏.


Ste*_*n C 9

提示:泄漏是在pop方法中.考虑对弹出对象的引用会发生什么......


Jon*_*erg 6

这里存在内存泄漏并非先验.

我认为教授要记住,你不是要弹出弹出的项目(换句话说,你回来后items[--size],你可能应该设置items[size] = null).但是当Foo实例超出范围时,一切都将被收集.所以这是一个相当弱的练习.

  • 他的意思是这样的:"Object result = items [size - 1]; items [size - 1] = null; size--; return result;"."result"变量仍然指向该对象. (5认同)