Java Tutorials - Herong's Tutorial Notes
Dr. Herong Yang, Version 6.00

Calculating Memory Usage of an Array

This section provides a tutorial example on how to calculate memory usage of a large array.

The memory infomation provided by the JVM can be used to calculate the memory usage of data objects used in the application program. In the following program, I tried to calculate the memory usage of an array:

/**
 * MemoryUsage.java
 * Copyright (c) 2002 by Dr. Herong Yang
 */
public class MemoryUsage {
   private static long[] fm = new long[2];	
   private static long[] tm = new long[2];	
   private static long[] mm = new long[2];	
   private static long[] um = new long[2];	
   public static void main(String[] a) {
      Runtime rt = Runtime.getRuntime();
      getMemoryInfo(rt,0);
      long[] la = null;
      long s = allocateLongArray(la);
      getMemoryInfo(rt,1);
      System.out.println("Memory usage before array allocation:");
      System.out.println("   Free memory = "+fm[0]);
      System.out.println("   Total memory = "+tm[0]);
      System.out.println("   Maximum memory = "+mm[0]);
      System.out.println("   Memory used = "+um[0]);
      System.out.println("Memory usage after array allocation:");
      System.out.println("   Free memory = "+fm[1]);
      System.out.println("   Total memory = "+tm[1]);
      System.out.println("   Maximum memory = "+mm[1]);
      System.out.println("   Memory used = "+um[1]);
      System.out.println("Memory usage summary:");
      System.out.println("   Allocated to the array = "+s);
      System.out.println("   Memory usage increase = "+(um[1]-um[0]));
      System.out.println("   Overhead of single array = "
         +(um[1]-um[0]-s));
   }
   public static void getMemoryInfo(Runtime rt, int i) {
      fm[i] = rt.freeMemory();
      tm[i] = rt.totalMemory();
      mm[i] = rt.maxMemory();
      um[i] = tm[i]-fm[i];
   }
   public static long getMemoryInfo(Runtime rt) {
      //rt.gc();
      System.out.println("Getting JVM memory infomation...");
      long fm = rt.freeMemory();
      long tm = rt.totalMemory();
      long mm = rt.maxMemory();
      System.out.println("   Free memory = "+fm);
      System.out.println("   Total memory = "+tm);
      System.out.println("   Maximum memory = "+mm);
      System.out.println("   Memory used = "+(tm-fm));
      return tm-fm;
   }
   public static long allocateLongArray(long[] la) {
      int s = 2*128*1024;
      la = new long[s]; // 2 MB needed for this array
      return 8*s;
   }
}

Output:

D:\herong\write_20021217\java_20021217\s
emoryUsage
Memory usage before array allocation:
   Free memory = 1777248
   Total memory = 2031616
   Maximum memory = 134217728
   Memory used = 254368
Memory usage after array allocation:
   Free memory = 1897280
   Total memory = 4132864
   Maximum memory = 134217728
   Memory used = 2235584
Memory usage summary:
   Allocated to the array = 2097152
   Memory usage increase = 1981216
   Overhead of single array = -115936

The output was very surprising. An array for storing 2097152 bytes (2MB) of data was allocated. But the memory usage was increased by only 1981216 bytes. Somehow the JVM freed up some memory during the array allocation process.

If you look closely on the values of total memory before and after the array allocation, you can see that the JVM had requested an additional 2MB of memory from the operating system into order to have enough memory to give to the array. My guess is that the expansion of total memory triggered a garbage collection call, which removed some un-used objects in the JVM.

One way to avoid the total memory expansion is to invoke the JVM with a starting total memory of 4MB, using the following command:

>c:\j2sdk1.4.1_01\bin\java -cp. -Xms4m MemoryUsage

Output:

Memory usage before array allocation:
   Free memory = 3874400
   Total memory = 4128768
   Maximum memory = 134217728
   Memory used = 254368
Memory usage after array allocation:
   Free memory = 1777232
   Total memory = 4128768
   Maximum memory = 134217728
   Memory used = 2351536
Memory usage summary:
   Allocated to the array = 2097152
   Memory usage increase = 2097168
   Overhead of single array = 16

This time the program worked as I expected. The memory usage increased 16 bytes more than the number of bytes needed to store the data elements of the array. So the 16 bytes is the overhead cost of memory for a one-dimension array. It is used to store the size of the array and other information about the array.

Sections in This Chapter

JVM and OS System Properties

System.setProperty() - Setting Your Own Properties

Runtime.getRuntime() - Getting the Runtime Object

freeMemory() - Getting JVM Free Memory Information

Calculating Memory Usage of an Array

exec() - Executing Operating System Commands

Dr. Herong Yang, updated in 2008
Calculating Memory Usage of an Array