views:

123

answers:

5

The following piece of code observed under JConsole shows a constant increase of the heap size. The heap reach a maximum of 25mb and then the GC runs and decease the heap size to almost 3MB. Is this the expected behavior ? I'm very surprised!

public class Dummy {
    public static void main(String[] args) {
        System.out.println("start");
        while(true){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

I'm using Snow Leopard.

+3  A: 

Yes, it's normal. You're not explicitly creating any objects, but you're calling methods that probably create some temporary objects as part of their implementation. Those temporary objects pile up until it's time for a GC run to clean them out.

Wyzard
+4  A: 

Yes, this should be the expected behaviour. While you are not doing anything specific to allocate objects, the implementation of sleep might be, and even if that doesn't, there are other threads running in the JVM, that could well be.

Paul Wagland
Yes, the other threads running are the most likely culprit. Thread.sleep just calls a native method.
Pool
+8  A: 

Communication with jconsole causes objects to be allocated. I believe what you are seeing here is is an artifact of your measurement method. There may also be slight allocation by HotSpot when compiling code. If you are worried, use a profiler to see what is being allocated (again, watch out for allocations by the profiler's interface).

Normal GC behaviour is to avoid running unnecessarily. You will see all over the web sawtooth graphs of memory usage. There is some compromise here between cache and swap friendliness and avoiding work. Also server HotSpot is more aggressive about using up memory than the client HotSpot.

Tom Hawtin - tackline
+1 - I'm sure that this is the answer. It is most unlikely that the class above will consume a noticeable amount of heap space in the loop. In fact, I'd expect zero allocations in the loop. Even if the JVM allocates (say) 100 bytes for each sleep call, it is going to take a VERY LONG TIME to reach 25Mb.
Stephen C
+2  A: 

The class files looks like that, the code loops from 8 to 14, and java.lang.Thread.sleep() is native. Therefore there is no reason to create MB's of objects

 public static void main(java.lang.String[] args);
     0  getstatic java.lang.System.out : java.io.PrintStream [16]
     3  ldc <String "start"> [22]
     5  invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
     8  ldc2_w <Long 5000> [30]
    11  invokestatic java.lang.Thread.sleep(long) : void [32]
    14  goto 8
    17  astore_1 [e]
    18  aload_1 [e]
    19  invokevirtual java.lang.InterruptedException.printStackTrace() : void [38]
    22  goto 8

I'm afraid what you see is from JProfiler itself (I don't know how you attached it to your Dummy test app) or other things running in this vm. To find out what objects have been created you should do a heap dump if JProfiler doesn't show this information.

'

stacker
Doesn't help. Native code can quite happily allocate Java heap objects.
Tom Hawtin - tackline
Maybe they implemented sleep like that: new Pillow(); ;-)
stacker
+1  A: 

There are clearly two theories as to the cause, and it is not possible to distinguish them based on empirical reasoning. Can I suggest a simple experiment.

  1. Change the program to sleep for 1 millisecond instead of 5000. (The actual number doesn't matter ... this is to make the hypothesized memory allocation happen as fast as possible. You could also try 0 milliseconds, but the behaviour of sleep may well be different ...)

  2. Run the program using the current approach; e.g. with jconsole.

  3. Run the program without jconsole, etc, but with the "-verbose:gc" option so that you can see when the GC runs.

I suspect that you will run out of patience waiting for the GC to run in the last case ... even calling sleep as fast as possible.

Stephen C
Or pointer a profiler at it.
Tom Hawtin - tackline
A profiler could conceivably result in unexplained allocations ... though this is unlikely.
Stephen C