Sometimes, we need to know how much memory Java objects occupy, someone to compare two times before and after two times System.GC () to calculate the size of the Java object, or the size of the estimated objects according to the Java object Memory in the Java Virtual Machine specification, These two methods are more or less problematic because System.GC () does not necessarily promote GC, the same type of object in 32-bit and 64-bit JVM uses the same memory, whether or not to turn on pointer compression in a 64-bit virtual machine can also affect the size of the Java object in memory. so is there an accurate and convenient way to calculate the size of an object? The answer is yes. The
instrumentation class was introduced in Java 5, which provides a way to compute the object's memory footprint, the hotspot supports the instrumentation framework, and other virtual machines provide a similar framework
The process of computing Java object Size using the instrumentation class is as follows:
- Create an agent class with the Premain method,
- The JVM will pass in a instrumentation object When invoking the Premain method of the agent class, calling instrumentation 's Getobjectsize method
- Make the agent class into a jar package
- Start our application and specify the path to the agent jar using the JVM parameter
The following is an example of calculating the size of an object object, which details the process of using instrumentation to calculate the size of objects1. Creating the Instrumentation Agent classThe instrumentation Agent class has a method Premain, declared as follows:
void Premain (String args, Instrumentation inst) { ... 3}
The JVM will call this method before the application runs (that is, before executing the application's main method), and the JVM will pass in an instance that implements the instrumentation interface when the method is called, and we can call Getobjectsize () method to calculate the size of the object. For example, to calculate the size of an object instance and a custom type MyObject instance, the agent code is as follows:
1PackageMy2ImportJava.lang.instrument.Instrumentation;345PublicClassmyagent {6PublicStaticvoidPremain (String args, instrumentation inst) {7 Object obj =new Object (); 8 System.out.println ("Bytes used by Object:" + inst.getobjectsize (obj)); 9 System.out.println ("Bytes used by MyObject:" + inst.getobjectsize (new MyObject ())); Ten }public static void main (string[] args) {System.out.println ("Main was over"
);
+}
The MyObject code is as follows:
Package my; Class myobject{new Object (); 5}
It is important to note that the agent class does not need to implement any interfaces, only the Premain method is defined, and the JVM automatically calls the method.
2. Package the agent class into a jar packagebefore packaging, you need to create a manifest file, create a manifest.txt file, including the following:
Premain-class:my. Myagent
Then execute the command to create the jar package
JAR-CMF manifest.txt Agent.jar my/*
3. Run the application using the agentrun the application and use the Javaagent command line parameter to specify the instrumentation agent's Jar file, add Classpath as the current directory and the Main method in In Com.mypackage.Main, the command is as follows:
JAVA-JAVAAGENT:AGENT.JAR-CP. My. Myagent
the results of running on a 32-bit machine are as follows:
[Email protected]:~/workspace/my/bin$ java-javaagent:agent.jar My. Myagent Bytes used by Object:8 Bytes used by myobject:16 main are over
On a 64-bit machine (does not turn on pointer compression) The result is as follows:
[Email protected] ~]$ Java-xx:-usecompressedoops-javaagent:agent.jar-CP. My. Myagentbytes used by object:16Bytes used by myobject:24main are over
On a 64-bit machine (turn on pointer compression) The result is as follows:
[Email protected]~]$ java-xx:+usecompressedoops-javaagent:agent.jar-cp. My. Myagent Bytes used by object:16 Bytes used by myobject:16 main are over
The run results show that the object objects occupy 8 bytes on the 32bit machine, 16 bytes on the 64bit machine, and 16 bytes on the 32bit machine for MyObject for a member of the object type. On the 64bit machine does not turn on the pointer compression is occupies 24 bytes, opens the pointer compression to occupy 16 bytes.
Accessing the Instrumentation object in the application
In the example above, we calculate the size of the object in the Premain method. But what if we want to calculate the size of an object during application execution?
1PublicClassmyagent {2PrivateStaticVolatileInstrumentation globalinstr;3PublicStaticvoidPremain (String args, instrumentation inst) {4 Globalinstr = inst; 5 } 6 public static long getobjectsize (Object obj) { 7 if (globalinstr = = null 8 throw new IllegalStateException ("Agent not initted" 9 return globalinstr.getobjectsize (obj); }11}
Myagent.getobjectsize () to calculate the size of any instance at run time.
deep Compute Object Memory usageNote the Getobjectsize method does not include the size of other objects that the object applies to. When you join object A To reference object B and use the Getobjectsize () method to calculate the size of object A, only the size of the object B reference (4byte) is included, not the true size of object B. How to calculate the size of an object in depth, I'll explain in detail in the next blog post.
How to calculate the size of Java objects accurately