java - 是内存泄漏吗?

标签 java memory-leaks

我构建了一个示例程序来演示 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)

我的问题是;

  1. 它没有调用finalize()。是不是内存泄漏?
  2. 直到 N=1000 为止,可用内存没有变化。但是当 N=1500 时,有 2 个不同的 程序结束时使用的内存值,即 282K 和 370K。 为什么会这样?
  3. 当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/

相关文章:

c++ - 内存泄漏,如何使用 MS Visual Studio 2012 检测导致内存泄漏的原因?

actionscript-3 - 您能期望 flash/as3 播放器最终进行垃圾收集吗?

java - 填写表格中的缺失值

java - 如何使用 gson 以纳秒精度反序列化 JSON 日期时间

java - 文件扫描器 : Unreported exception FileNotFoundException; must be caught or declared to be thrown

android - 使用位图和 Volley 查看寻呼机内存泄漏

xml - 使用拉式解析器的 Scala 内存泄漏

java - 如何修复返回值未显示在我的方法之一上的问题

java - 我们可以使用硬盘空间作为jvm内存吗

c++ - 为什么使用 'new'会导致内存泄漏?