Java 向量和垃圾收集器
我正在运行一个使用许多向量的java程序。我担心我使用它们会导致垃圾收集器无法工作 我有许多这样做的线程:Java 向量和垃圾收集器,java,garbage-collection,vector,Java,Garbage Collection,Vector,我正在运行一个使用许多向量的java程序。我担心我使用它们会导致垃圾收集器无法工作 我有许多这样做的线程: vec.addAll(<collection>); vec.remove(0); 我有打印输出,显示向量有时是空的,但我想知道内存是否真的被释放了 我需要担心吗?如果没有对相关对象的引用,内存最终将被释放。看到向量变为空表示它们至少没有保留引用。如果对这些对象的引用没有其他内容,它们将被清除,但只有当垃圾收集器选择这样做时(这总是在内存耗尽之前)。不,您没有。如果向量为空,
vec.addAll(<collection>);
vec.remove(0);
我有打印输出,显示向量有时是空的,但我想知道内存是否真的被释放了
我需要担心吗?如果没有对相关对象的引用,内存最终将被释放。看到向量变为空表示它们至少没有保留引用。如果对这些对象的引用没有其他内容,它们将被清除,但只有当垃圾收集器选择这样做时(这总是在内存耗尽之前)。不,您没有。如果向量为空,则它不会引用您放置在其中的对象。如果您想知道哪些内容占用了内存,可以使用探查器查看哪些内容占用了内存。否 只要相信标准库的实现者就行了。他们可能做得很好 如果您真的担心内存泄漏,请随时调用此选项:
System.out.println("Total Memory"+Runtime.getRuntime().totalMemory());
System.out.println("Free Memory"+Runtime.getRuntime().freeMemory());
(注意:显然,调用remove(0)只会从向量中删除第一个元素,而不会删除多个元素。)
假设您的向量
为空,那么如果向量中的对象未在其他地方引用,则无需担心垃圾收集。但是,如果仍然存在对对象的其他引用,则无法对其进行垃圾收集
为了验证这一点,我建议运行一个探查器(例如JProfiler),并定期“捕捉”存储在向量中的对象类型的对象计数,然后监视此计数是否随时间增加
另一条建议:Vector
已过时;您应该考虑使用LIKEDLIST或ARAYLIST,这是线程不安全的等价物。如果您希望使它们成为线程安全的,您应该使用Collections.synchronizedList(new ArrayList())初始化它们代码>如果向量中的对象没有被任何地方引用(由向量或任何其他代码引用),那么它们将由垃圾收集器自行收集。99.999%的时间垃圾收集器不需要您的帮助
但是,即使在垃圾收集器释放对象之后,它也可能不会将堆内存返回给操作系统,因此您的进程可能会比它应该拥有的内存更多
此外,我不太熟悉Vector类的实现(正如其他人所指出的,实际上应该使用ArrayList
),但是当调用.remove()
时,我认为底层数组的大小永远不会向下调整。因此,如果您将数千个对象填充到一个向量中,然后将它们全部删除,它可能仍会分配数千字节的空数组。本例中的解决方案是调用。jdk1.6中java.util.Vector.remove(int)的实现是:
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
Object oldValue = elementData[index];
int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--elementCount] = null; // Let gc do its work
return (E)oldValue;
}
如您所见,如果从向量中删除元素,向量将不会保留对它们的引用,因此不会妨碍它们的垃圾收集
但是,向量本身(以及支持它的潜在大数组)可能无法回收。不,Java有几种垃圾收集器,但据我所知,没有一种可以使用引用计数;如果对象图中存在循环,引用计数策略将失败,因为引用计数永远不会达到零。确定。我关于引用计数的旁白被删除了。您现在可以给我一些提点:-)+1:关于底层数组没有自动调整大小的观点很好。ArrayList具有相同的功能。