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:
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.