2 Replies Latest reply: Mar 18, 2011 12:17 AM by Rahul Bakale RSS

    MemoryMxBean.getHeapMemoryUsage().getUsed() does not return accurate size

    Rahul Bakale
      Hi,
      I am getting some strange results while using MemoryMxBean.getHeapMemoryUsage().getUsed(). At the bottom of the post is the program I am running. It takes a count as a parameter and create those number of instances of java.lang.Object. With every new instance created, I am expecting the heap usage to increase. However, the heap usage returned by MemoryMxBean does not increase linearly with the number of instances created.

      For example:

      On Windows XP_, for count of *9000*, the heap usage was shown as follows:

      0 to 669 objects : 344736
      670 to 3509 objects : 481088
      3510 to 6349 objects : 617440
      6350 to 9000 objects : 753792

      On Windows XP_, for count of *9001*, the heap usage is shown as follows:

      0 to 669 objects : 344744
      670 to 3509 objects : 481096
      3510 to 6349 objects : 617448
      6350 to 9001 objects : 753800

      On HP-UX_, for count of *9000*, the heap usages is shown as follows:

      0 to 331 objects : 300896
      332 to 1014 objects : 333704
      1015 to 1697 objects : 366512
      1698 to 2380 objects : 399320
      2381 to 3063 objects : 432128
      3064 to 3746 objects : 464936
      3747 to 4429 objects : 497744
      4430 to 5112 objects : 530552
      5113 to 5795 objects : 563360
      5796 to 6478 objects : 596168
      6479 to 7161 objects : 628976
      7162 to 7844 objects : 661784
      7845 to 8527 objects : 694592
      8528 to 9000 objects : 727400

      I was expecting an increase in usage with every new object being created. When I use HPROF, instead of MemoryMxBean, it shows me accurate heap usage.
      So, is there a bug in MemoryMxBean or am I missing something?

      The command line parameters used were: -Xloggc:gc.log -Xms24m -Xmx24m

      GC never ran during any of the runs.

      This behavior was observed on following machines/VMs:

      1. Windows XP, HotSpot(TM) Client VM (build 19.0-b09, mixed mode, sharing), Runtime Environment (build 1.6.0_23-b05), Min/Max heap size 24 MB.
      2. HP-UX, HotSpot(TM) Server VM (build 1.6.0.02 jinteg:09.26.08-16:50 PA2.0 (aCC_AP), mixed mode), Runtime Environment (build 1.6.0.02-jinteg_26_sep_2008_17_44-b00)


      The program I am using is as follows:
      import java.lang.management.ManagementFactory;
      import java.lang.management.MemoryMXBean;
      
      public class Main {
           private static Object[] objs;
           
           public static void main(final String[] args) {
                
                if (args == null || args.length == 0) throw new IllegalArgumentException("count not specified");
                if (args.length > 1) throw new IllegalArgumentException("too many arguments");
                
                final int count = Integer.parseInt(args[0]);
                if (count < 1) throw new IllegalArgumentException("count should be a positive integer");
                
                final MemoryMXBean bean = ManagementFactory.getMemoryMXBean();
                objs = new Object[count];
                final long[] usages = new long[count + 1];
                usages[0] = bean.getHeapMemoryUsage().getUsed();
      
                for (int k = 0; k < count; k++) {
                     objs[k] = new Object();
                     usages[k + 1] = bean.getHeapMemoryUsage().getUsed();
                }
                
                final StringBuilder sb = new StringBuilder();
                long record = usages[0];
                sb.append(0);
                
                for (int k = 1; k <= count; k++) {
                     if (usages[k] != record) {
                          sb.append(" to ").append(k - 1).append(" : ").append(record).append("\n");
                          sb.append(k);
                          record = usages[k];
                     }
                }
                sb.append(" to ").append(count).append(" : ").append(record);
                System.out.print(sb);
           }
      }
        • 1. Re: MemoryMxBean.getHeapMemoryUsage().getUsed() does not return accurate size
          jtahlborn
          you seem to be assuming that the "main" program thread is the only thread doing anything in your program. however, if you do a thread dump of even the simplest java program, you will see a few other threads running as well which are used by the jvm to perform various tasks). these other threads will be using memory in a completely non-deterministic (and uncontrollable by you) way which will certainly influence your memory readings.
          • 2. Re: MemoryMxBean.getHeapMemoryUsage().getUsed() does not return accurate size
            Rahul Bakale
            Thanks. I am aware that there are threads other than "main" which are running (like Finalizer, GC etc). If other threads are using memory in a completely non-deterministic manner, I should random values of heap usage. But I don't see random values - i see a fixed heap usage until object count increases from X to Y, then heap usage increases at Y+1 and remains same until object count reaches Y+1+Z and so on.

            Also, if it is really un-deterministic, why does HPROF give accurately predicatable increase in heap with every object?