简体   繁体   中英

What is the cause of a memory leak?

I don't find the cause of a memory leak. I use showMemoryUse() to get the used memory before and after the stack. I observe that I lose memory. What's wrong with my code ? Anyone can help me? Thank's in advance

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();
}

}

you should use a java memory analyzer to get what are the objects that are leaking.

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

after download, you need to get a heapdump file of your application runtime. a heapdump will have all the objects that were being used and memory accumulation.

use the memory analyzer to open the heapdump file and then start navigate inside to see which object has the most memory utilized. from there you can then enhancing your codes to nullify or to close some objects.

You didn't specify how you're measuring memory.

Anyway, short story: Your code is fine, the Stack class doesn't leak memory. Nor does main().

More details below.

In your example, ensureCapacity() never doubles the allocated size. If you want, you can put a 'System.out' there inside the if() from ensureCapacity(), and you'll see it's never displayed. Which is normal, since you're initializing the Stack with 10000 elements and put 10000 elements. They fit, so there's no need to increase the size. That would have been a place where memory would have been used. (Not leaked though)

I think that what's shown to you as memory leaks in between the 'showMemoryUse()' calls is the creation of string objects.

Whenever you do "a wallet, wallet, wallet, wallet, string " + i, a String object is created.

Actually, there's more to that. A String object called "a wallet, wallet, wallet, wallet, string " is created once and stored in Java's string pool. Then, a StringBuilder is created and is used to concatenate that string and i. Then, the result of the StringBuilder is stored in a new String.

You can see all the above information with the 'javap' tool.

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's optimized to run fast even with the creation of these auxiliary objects, and they'll be eventually garbage-collected.

What I'm trying to say is: don't worry about it. There are no leaks in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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