簡體   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