繁体   English   中英

内存泄漏的原因是什么?

[英]What is the cause of a memory leak?

我没有发现内存泄漏的原因。 我使用showMemoryUse()来获取堆栈前后的已用内存。 我发现我失去了记忆。 我的代码有什么问题? 有人可以帮助我吗? 提前致谢

import java.util.EmptyStackException;

public class Stack {
private Object[] tools;
private int size = 0;

public Stack(int initialCapacity) {
    tools= new Object[initialCapacity];
}

public void push(Object object) {
    ensureCapacity();
    tools[size++] = object;
}

public Object pop() {
    if (size == 0){
        throw new EmptyStackException();
    }
    return tools[--size];
}

private void ensureCapacity() {
    if(tools.length == size){
        Object[] old = tools;
        tools = new Object[2 * size + 1];
        System.arraycopy(old, 0, tools, 0, size);
    }

}

public static void main(String[] args) {
    Stack stack = new Stack(10000);
    showMemoryUse();

    for ( int i = 0; i< 10000; i++){
        stack.push("a wallet, wallet, wallet, wallet, string " + i);
    }
    for ( int i = 0; i< 10000; i++){
        System.out.println(stack.pop());
    }
    showMemoryUse();
}

}

您应该使用Java内存分析器来获取泄漏的对象。

https://www.eclipse.org/mat/

下载后,您需要获取应用程序运行时的heapdump文件。 一个堆转储将具有所有正在使用的对象和内存累积。

使用内存分析器打开heapdump文件,然后开始在内部导航以查看哪个对象使用的内存最多。 然后,您可以从那里增强代码以使某些对象无效或关闭它们。

您没有指定测量内存的方式。

总之,简而言之:您的代码很好,Stack类不会泄漏内存。 main()也没有。

下面有更多详细信息。

在您的示例中,ensureCapacity()决不会使分配的大小增加一倍。 如果需要,您可以在sureCapacity()的if()内部放置一个“ System.out”,您将看到它永远不会显示。 这很正常,因为您要使用10000个元素初始化Stack并放置10000个元素。 它们适合,因此无需增加尺寸。 那将是使用内存的地方。 (虽然没有泄漏)

我认为,在“ showMemoryUse()”调用之间出现内存泄漏时,显示给您的是字符串对象的创建。

每当您执行“皮夹,皮夹,皮夹,皮夹,字符串” + i时,都会创建一个String对象。

实际上,还有更多。 创建一次名为“钱包,钱包,钱包,钱包,字符串”的String对象,并将其存储在Java的字符串池中。 然后,创建一个StringBuilder并将其用于连接该字符串和i。 然后,将StringBuilder的结果存储在新的String中。

您可以使用“ javap”工具查看上述所有信息。

javap -c Stack.class

  13: invokestatic  #60                 // Method showMemoryUse:()V
  16: iconst_0
  17: istore_3
  18: goto          48
  21: new           #63                 // class java/lang/StringBuilder
  24: dup
  25: ldc           #65                 // String a wallet, wallet, wallet, wallet, string
  27: invokespecial #67                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  30: iload_3
  31: invokevirtual #69                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  34: invokevirtual #73                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  37: astore        4
  39: aload_2
  40: aload         4
  42: invokevirtual #77                 // Method push:(Ljava/lang/Object;)V

Java经过优化,即使创建了这些辅助对象也可以快速运行,并且最终将对其进行垃圾回收。

我想说的是:不用担心。 您的代码中没有泄漏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM