Monitoring the size of your Java objects with Java Object Layout
In this tutorial you will learn how you can use the JOL (Java Object Layout) toolbox to monitor the size of Java Objects.
JOL is tiny toolbox available in OpenJDK to analyze Java object layout schemes. This tool uses Unsafe, JVMTI, and Serviceability Agent (SA) heavily to decoder the actual object layout, footprint, and references. This makes JOL much more accurate than other tools relying on heap dumps, specification assumptions, etc.
You can use JOL in different ways, as a Command Line Tool or using directly its API in your code.
Using JOL as Command Line Utility
As command line utility, you will have at first to clone the project available at: http://hg.openjdk.java.net/code-tools/jol/ Then build JOL with Maven:
$ cd jol/
$ mvn clean install
Now you can run the executable JAR file jol-cli.jar to get:
- Object internals, that is instances of that object
- Object externals, that is, the objects reachable from the instance
$ java -jar jol-cli/target/jol-cli.jar internals java.util.HashMap
Running 64-bit HotSpot VM.
Using compressed oop with 3-bit shift.
Using compressed klass with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
java.util.HashMap object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 05 00 00 00 (0000 0101 0000 0000 0000 0000 0000 0000)
4 4 (object header) 00 00 00 00 (0000 0000 0000 0000 0000 0000 0000 0000)
8 4 (object header) 8c 3b 00 f8 (1000 1100 0011 1011 0000 0000 1111 1000)
12 4 Set AbstractMap.keySet null
16 4 Collection AbstractMap.values null
20 4 int HashMap.size 0
24 4 int HashMap.modCount 0
28 4 int HashMap.threshold 0
32 4 float HashMap.loadFactor 0.75
36 4 Node[] HashMap.table null
40 4 Set HashMap.entrySet null
44 4 (loss due to the next object alignment)
Instance size: 48 bytes (reported by Instrumentation API)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
Calculate objects size from your code
if you need to calculate at runtime the size of your objects, then you need at first to include its dependency so that you can build your project:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.8</version>
</dependency>
Once done, you will be able to access the org.openjdk.jol package as in the following example class:
package com.mastertheboss;
import java.util.ArrayList;
import java.util.List;
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.info.GraphLayout;
public class MemoryTest {
@SuppressWarnings("restriction")
public static void main(String[] args) {
int size = 10;
List<Integer> list = new ArrayList<Integer>(size);
for (int i = 0; i < size; i++) {
list.add(i);
}
System.out.println(ClassLayout.parseClass(ArrayList.class).toPrintable());
System.out.println(ClassLayout.parseClass(ArrayList.class).toPrintable(list));
System.out.println(GraphLayout.parseInstance(list).toPrintable());
System.out.println(GraphLayout.parseInstance(list).toFootprint());
}
}
The first method, that is:
System.out.println(ClassLayout.parseClass(ArrayList.class).toPrintable());
Produces a printable stringly representation of class layout. This method does not require alive instance, just the class.
java.util.ArrayList object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 12 (object header) N/A
12 4 int AbstractList.modCount N/A
16 4 int ArrayList.size N/A
20 4 java.lang.Object[] ArrayList.elementData N/A
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
On the other hand, next one:
System.out.println(ClassLayout.parseClass(ArrayList.class).toPrintable(list));
Produces a String representation of a live class instance with its objects:
java.util.ArrayList object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 9e 36 00 f8 (10011110 00110110 00000000 11111000) (-134203746)
12 4 int AbstractList.modCount 10
16 4 int ArrayList.size 10
20 4 java.lang.Object[] ArrayList.elementData [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
In order to produce a representation of graph of external objects, we’ll use the following method:
System.out.println(GraphLayout.parseInstance(list).toPrintable());
Which produces this output for our ArrayList:
java.util.ArrayList@368102c8d object externals:
ADDRESS SIZE TYPE PATH VALUE
782faf2d0 16 java.lang.Integer .elementData[0] 0
782faf2e0 16 java.lang.Integer .elementData[1] 1
782faf2f0 16 java.lang.Integer .elementData[2] 2
782faf300 16 java.lang.Integer .elementData[3] 3
782faf310 16 java.lang.Integer .elementData[4] 4
782faf320 16 java.lang.Integer .elementData[5] 5
782faf330 16 java.lang.Integer .elementData[6] 6
782faf340 16 java.lang.Integer .elementData[7] 7
782faf350 16 java.lang.Integer .elementData[8] 8
782faf360 16 java.lang.Integer .elementData[9] 9
782faf370 246184 (something else) (somewhere else) (something else)
782feb518 24 java.util.ArrayList (object)
782feb530 56 [Ljava.lang.Object; .elementData [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
And finally, in order to calculate the memory footprint of the ArrayList:
System.out.println(GraphLayout.parseInstance(list).toFootprint());
Here’s the output:
java.util.ArrayList@368102c8d footprint:
COUNT AVG SUM DESCRIPTION
1 56 56 [Ljava.lang.Object;
10 16 160 java.lang.Integer
1 24 24 java.util.ArrayList
12 240 (total)
Recommended Articles
Monitor WildFly with CLI and Bash: A Simple Approach to Application Server Monitoring
Learn how to monitor your WildFly application server using only Java Management Extensions (JMX) CLI, bash, and awk. Automate alerts for key attributes like available connections and free heap memory.
Enhance Your Java EE Applications with WildFly Monitoring using Prometheus - A Comprehensive Guide
Learn how to set up and utilize Prometheus for monitoring your WildFly applications. Explore key features like multi-dimensional data model and flexible query language.
Monitor Your Java Application Server with Hawtio: A Step-by-Step Guide
Learn how to use Hawtio as an open-source monitoring solution for JVM middleware like JBoss Enterprise Application Server and WildFly, with a single point of management across multiple middleware.
Mastering Java Process Monitoring with jcmd: A Step-by-Step Guide
Learn how to monitor and diagnose Java processes using the powerful jcmd tool. Get expert tips on gathering diagnostic information, troubleshooting issues, and optimizing performance.