我有一个简单的例子。该示例加载 ArrayList<Integer>
来自文件 f
包含 10000000 个随机整数。
doLog("Test 2");
{
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);
List<Integer> l = (List<Integer>) ois.readObject();
ois.close();
fis.close();
doLog("Test 2.1");
//l = null;
doLog("Test 2.2");
}
doLog("Test 2.3");
System.gc();
doLog("Test 2.4");
当我有 l = null
,我得到这个日志:
Test 2 Used Mem = 492 KB Total Mem = 123 MB
Test 2.1 Used Mem = 44 MB Total Mem = 123 MB
Test 2.2 Used Mem = 44 MB Total Mem = 123 MB
Test 2.3 Used Mem = 44 MB Total Mem = 123 MB
Test 2.4 Used Mem = 493 KB Total Mem = 123 MB
但是当我删除它时,我得到的是这个日志。
Test 2 Used Mem = 492 KB Total Mem = 123 MB
Test 2.1 Used Mem = 44 MB Total Mem = 123 MB
Test 2.2 Used Mem = 44 MB Total Mem = 123 MB
Test 2.3 Used Mem = 44 MB Total Mem = 123 MB
Test 2.4 Used Mem = 44 MB Total Mem = 123 MB
Used Memory
计算方式:runTime.totalMemory() - runTime.freeMemory()
问题如果l = null;
存在,是否存在内存泄漏?
l
是不可访问的,那么为什么不能释放它呢?
最佳答案
上面的代码没有内存泄漏。
一旦您离开包含在 {}
中的代码块,变量 l
就会超出范围,List
是一个垃圾收集的候选对象,无论您是否先将其设置为 null
。
但是,在代码块之后和方法返回之前,List
处于称为不可见 的状态。虽然这是事实,但 JVM 不太可能自动清空引用并收集 List
的内存。因此,显式设置 l = null
可以帮助 JVM 在您进行内存计算之前收集内存。否则,它将在方法返回时自动发生。
对于不同的代码运行,您可能会得到不同的结果,因为您永远不知道垃圾收集器何时运行。您可以建议您认为它应该使用 System.gc()
运行(它甚至可能收集不可见的 List
,即使没有设置 l = null
),但没有 promise 。在 javadoc for System.gc() 中说明:
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
关于java - 这个 Java 示例会导致内存泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12029823/