2

I do not know how to answer this question. Instead, I told them that I have not see any practical code/situation in a Web Application that could a memory leak. I also told him that if there are too many object being created and these objects going out of scope, the GC will take care of reclaiming the memory.

My questions are (1) Was my answer good enough ? (2) Can you please give me a practical example of the Java Memory leak in a Web and/or non-Web environment?

Thanks

shortduck
  • 1,437
  • 1
  • 8
  • 13

3 Answers3

6

Good topic!

You need to monitor Java memory consumption first.

The simplest way to do this is to use jstat utility that comes with every JVM.

jstat -gcutil <process_id> <timeout>

It will report memory consumption for each generation (Young, Eldery and Old) and garbage collection times (Young and Full).

As soon as you spot that Full Garbage Collection is executed too often and takes too much time, you can assume that application is leaking memory.

Then you need to create a memory dump using jmap utility:

jmap -dump:live,format=b,file=heap.bin <process_id>

Then you need to analyse heap.bin file with Memory Analyser, Eclipse Memory Analyzer (MAT) for example.

MAT will analyze the memory and provide you suspect information about memory leaks.

Pavel Molchanov
  • 2,299
  • 1
  • 19
  • 24
  • Ok, I will keep him on my radar next time. Thank you for the vote up. From my experience, it's the easiest way to monitor memory consumption without external tools. There was 'jhat' utility for reading memory dumps but it was deprecated due to the unreliable statistics. FlightRecorder is another good option but it's available only with commercial features enabled in Java. Hope that in next Java versions FlightRecorder will be available in the free version. – Pavel Molchanov Jun 15 '18 at 19:40
  • I wouldnt go so far as putting people on radars or "blacklists". There are simply too many of them. Tell them what needs to be said, and move on. If he continues like that, it won't be long anyway, before his account gets suspended. – GhostCat Jun 15 '18 at 19:43
  • Ok, I got it! Thanks :) – Pavel Molchanov Jun 15 '18 at 19:44
1

A memory leak, is any situation where you continue to hold on to allocated memory you no longer need and no longer intend to use.

Consider the following example:

public class LeakMemory {
    private static final List<String> LEAK = new ArrayList<>();

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("What is your name? ");
        while (in.hasNext()) {
            name = in.next();
            System.out.println("Hi " + name);
            LEAK.add(name);
        }
    }
}

The LEAK list is grows in every iteration, and there's no way to free it up, yet it's never used. This is a leak.

amrender singh
  • 7,949
  • 3
  • 22
  • 28
0

By the normal definition of a memory leak, Java does not have them due to Garbage collection. If we, however, expand the definition a little bit to "Objects the program does not need anymore, but are not garbage-collectible", then there are two scenarios I can think of where such "leaks" could arise.


Scenario 1: record all objects of a class ever created

This example has an artificial taste and is often seen in the context of an exercise. Suppose we want to store every instance of a certain class ever created. This can be achived through a static colleciton:

public class RecordMe {
  private static final List<RecordMe> created = new ArrayList<RecordMe>();
  ...
  private final int someValue;

  private RecordMe(final int someValue) {
    this.someValue = someValue;
  }

  public static RecordMe of(final int someValue) {
    RecordMe me = new RecordMe(someValue);
    created.add(me);
    return me;
  }

  public static List<RecordMe> instances() {
    return Collections.unmodifiableList(created);
  }
}

As soon as an instance of RecordMe is created, it can never be garbage-collected because it will always be referenced through the static list.

The fix would be to check the list before creating a new instance of RecordMe or use List<WeakReference<RecordMe>> (and clean this list from time to time).


Scenario 2: Leaks through inner classes

As we know, a non-staitc inner class holds an implicit reference to the object it was created from. Let's take a look on an extreme example.

public class MemoryTest {
  // data has a size of a little over 512 MB.
  private final byte[] data = new byte[1024 * 1024 * 512];
  private final Field field;

  public class Field {
  }

  public MemoryTest() {
    this.field = new Field();
  }

  public Field getField() {
    return this.field;
  }

  public static void main(String... args) {
    MemoryTest test = new MemoryTest();
    Field fieldOne = test.getField();
    test = null;
    test = new MemoryTest();
  }
}

If we execute this code with java -Xmx800m MemoryTest, it will throw an OutOfMemoryException. Examples of this sizes are unrealistic in the real, but in smaller sizes and with enough instances, this can also lead to issues. Take, for example, Java's HashMap-implementation. Method keySet() returns an instance of a non-static, inner class. As long as one holds instances to those inner classes, the HashMap cannot be garbage-collected.

Turing85
  • 18,217
  • 7
  • 33
  • 58