我构建了一个示例程序来演示 Java 中的内存泄漏。
public class MemoryLeakTest {
static int depth = 0;
int number=0;
MemoryLeakTest mobj;
MemoryLeakTest(){
number = depth;
if(depth < 6500){
depth++;
mobj = new MemoryLeakTest();
}
}
protected void finalize(){
System.out.println(number + " released.");
}
public static void main(String[] args) {
try{
System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());
System.out.println("Free Memory in starting "+ Runtime.getRuntime().freeMemory());
MemoryLeakTest testObj = new MemoryLeakTest();
System.out.println("Free Memory in end "+ Runtime.getRuntime().freeMemory());
System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());
}
catch(Exception exp){}
finally{
System.out.println("Free Memory"+ Runtime.getRuntime().freeMemory());
System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());
}
}
}
我通过更改if(depth < N)
中的N值来运行它。这是结果;
当深度为 1000 时
init = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 启动时的可用内存 15964120 最后释放内存 15964120 初始化 = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 可用内存 15964120 初始化 = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K)
当深度为 1500 时
init = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 启动时的可用内存 15964120 最后释放内存 15964120 初始化 = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 可用内存 15873528 初始化 = 16777216(16384K) 使用 = 379400(370K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K)
深度为 6000 时
init = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 启动时的可用内存 15964120 最后释放内存15692784 初始化 = 16777216(16384K) 使用 = 560144(547K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 可用内存 15692784 初始化 = 16777216(16384K) 使用 = 560144(547K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K)
当深度为 6500 时(线程“main”java.lang.StackOverflowError 中出现异常)
init = 16777216(16384K) 使用 = 288808(282K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K) 启动时的可用内存 15964120 最后剩余内存 15676656 初始化 = 16777216(16384K) 使用 = 576272(562K) 提交 = 16252928(15872K) 最大值 = 259522560(253440K)
我的问题是;
- 它没有调用finalize()。是不是内存泄漏?
- 直到 N=1000 为止,可用内存没有变化。但是当 N=1500 时,有 2 个不同的 程序结束时使用的内存值,即 282K 和 370K。 为什么会这样?
- 当N=6500时,JVM产生错误。那么为什么最后2 执行 try{} 语句。
最佳答案
你的程序不会“泄漏”,因为 Java 会处理任何“悬空”的东西。这就是垃圾收集语言的好处。
但是您遇到的是 StackOverFlow 错误。基本上,堆栈(即您所在的函数链及其深度)比堆小得多。堆“或多或少”是主内存的大小。每个线程的堆栈要小得多。基本上,你通过做你的“深度”事情就达到了这个极限。
如果你想测试“泄漏”(或者你最终不会有任何泄漏的想法),请尝试类似这样的东西:
public class MemoryLeakTest {
int number=0;
public MemoryLeakTest mobj;
MemoryLeakTest(int num){
number = num;
}
protected void finalize(){
System.out.println(number + " released.");
}
public static void main(String[] args) {
try{
System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());
System.out.println("Free Memory in starting "+ Runtime.getRuntime().freeMemory());
MemoryLeakTest first = new MemoryLeakTest(0); // Keep a reference to one of them
MemoryLeakTest current = first;
for(int i = 1; i < Int.Parse(args[0]); i++) // forgive me, Java's been a while. This may be C#. But parse the first arg for your number of objects
{
current.mobj = new MemoryLeakTest(i);
current = current.mobj;
}
System.out.println("Free Memory in end "+ Runtime.getRuntime().freeMemory());
System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());
}
catch(Exception exp){}
finally{
System.out.println("Free Memory"+ Runtime.getRuntime().freeMemory());
System.out.println(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage());
}
}
}
这将为您提供一个全部位于内存中的对象“链”,直到 first
超出范围。
关于java - 是内存泄漏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10308965/