Java Tutorials - Herong's Tutorial Examples - v8.22, by Herong Yang
Calculating Memory Usage of an Array
This section provides a tutorial example on how to calculate memory usage of a large array.
The memory information 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) HerongYang.com. All Rights Reserved. */ 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 information..."); 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:
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:
herong> java -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.
Table of Contents
Execution Process, Entry Point, Input and Output
Primitive Data Types and Literals
Bits, Bytes, Bitwise and Shift Operations
Managing Bit Strings in Byte Arrays
Reference Data Types and Variables
StringBuffer - The String Buffer Class
►System Properties and Runtime Object Methods
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
Generic Classes and Parameterized Types
Generic Methods and Type Inference
Lambda Expressions and Method References
Java Modules - Java Package Aggregation
Execution Threads and Multi-Threading Java Programs
ThreadGroup Class and "system" ThreadGroup Tree
Synchronization Technique and Synchronized Code Blocks
Deadlock Condition Example Programs
Garbage Collection and the gc() Method
Assert Statements and -ea" Option