Staying up late is not easy, and the line and cherish. Welcome old iron people one key three connect, give an encouragement, extremely thank you.


How do you know the size of an object in memory? C has a thing called sizeOf, which makes it easy to figure out how big an object is. But Java has no such thing. Don’t panic. Java has an Agent technology.

Java Agent technology

What is the mechanism of Agent?

When a JVM loads a class into memory, it can add an Agent Agent to load the memory. The Agent can capture the class file (001 010) and make arbitrary changes to it. Of course, it can also read the size of the entire Object.

See this article to learn more about the principles and practices of Java dynamic debugging

Create an Agent that detects the size of Object

Create a new project, ObjectSizeAgent, and make it a JAR package.

  1. Write an Agent class with a fixed format
public class ObjectSizeAgent {

    //Java internal bytecode processing debugging uses Instrumentation
    // So the Instrumentation can be intercepted when the proxy is loaded into our JVM
    private static Instrumentation inst;
  / * ** You must have premain* Fixed parameters* The second parameter is Instrumentation, which is called by the virtual machine and will automatically initialize Instrumentation for us* Here by assigning to their own defined member variables, assign value can get Instrumentation * @param agentArgs  * @param _inst * /  public static void premain (String agentArgs, Instrumentation _inst) {  inst = _inst;  }   / * ** After you get the Instrumentation in Premain, you can call getObjectSize to get the size of the object * @param o  * @return * /  public static long sizeOf (Object o) {  return inst.getObjectSize(o);  } } Copy the code
  1. Making jars

Different IDE tools type jars in different ways.

The process of opening jar in IDEA 2020.2 is as follows:

File->Project Structure


Choose the Artifacts


Enter the jar name, create the ManiFest, and store it in the SRC directory


After the creation, the directory is as follows:


The contents of the manifest.mf file:

Manifest-Version: 1.0
Premain-Class: pers.xblzer.tryout.agent.ObjectSizeAgent
Copy the code

Finally, make a JAR package:



Use Agent to detect Object size

Import the jars you made in your lab project, either maven or regular JAR.

PS: LET me write the process of making maven JARS at a cost.

  1. Copy the jar package to a place, D:\works\3rd_jar, nothing more, just for convenience
  2. packaging
MVN install: install-file-dgroupid =pers.xblzer.tryout -dartifactid =ObjectSizeAgent -dversion =1.0 -dpackaging =jar -Dfile=D:\works\3rd_jar\ObjectSizeAgent.jar -DgeneratePom=true -DcreateChecksum=true -Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true
Copy the code
  1. Other project references:
<dependency>
    <groupId>pers.xblzer.tryout</groupId>
    <artifactId>ObjectSizeAgent</artifactId>
    <version>1.0</version>
</dependency>
Copy the code

Experiment code:

public class TestObjectSize {

    public static void main(String[] args) {
/ / / / configuration XX: XX: + UseCompressedClassPointer + UseCompressedOops
        // 16 bytes = markword 8 + CLASspointer 4 + padding 4
 System.out.println("new Object size:" + ObjectSizeAgent.sizeOf(new Object()));  // 16 bytes = markword 8 + classpointer 4 + array length 4 + padding 0  System.out.println("new array size:" + ObjectSizeAgent.sizeOf(new int[] {})); // 32 (must be a multiple of 8 eventually)  System.out.println("new a common class size:" + ObjectSizeAgent.sizeOf(new P()));   XX: / / configuration - UseCompressedClassPointer XX: + UseCompressedOops  // 16 bytes = markword 8 + CLASspointer 8 + padding 0 // System.out.println("new Object size:" + ObjectSizeAgent.sizeOf(new Object())); // // 24 bytes = Markword 8 + CLASspointer 8 + array length 4 + padding 4 // System.out.println("new array size:" + ObjectSizeAgent.sizeOf(new int[]{})); // // 40 (must eventually satisfy multiples of 8) // System.out.println("new a common class size:" + ObjectSizeAgent.sizeOf(new P()));  }   private static class P {  // markword 8  / / ClassPinter (4 - UseCompressedClassPointer 8; + UseCompressedClassPointer is 4)   / / 4  int id;  // Oops 4  String name;// This is a reference to +UseCompressedOops 8 -UseCompressedOops 4  / / 1  byte b1;  / / 1  byte b2;  //Oops 4  Object o;  / / 8  long i;  } } Copy the code

The runtime adds the agent we made: the runtime adds the run parameters

-javaagent:D:\works\3rd_jar\ObjectSizeAgent.jar
Copy the code

JDK 1.8. JVM parameters are default:


From the running results

New Object() takes 16 bytes;

New int[]{} occupies 16 bytes;

The class defined by new P() itself that contains various data type attributes takes 40 bytes.

Now that the results are in, let’s analyze why they’re taking up so many bytes.

Layout of objects in memory

As the memory layout of objects is divided into two kinds, one is ordinary objects, one is array objects.

Allocation of bytes occupied by each part of common object memory:

  1. Object headers, called in HotspotmarkwordAnd its length is 18byte
  2. ClassPointerPointers (such as object.class)
  • For – XX: + UseCompressedClassPointers situation4byte, the default
  • The situation for XX: – UseCompressedClassPointers8byte
  1. The instance data

Where reference type byte usage:

  • -XX:+UseCompressedOops 4byte, the default
  • -XX:-UseCompressedOops 8byte

Usage of non-reference type bytes:

type storage Value range
int 4byte Minus 2^31 to 2^ 31-1
short 2byte Minus 2 to the 15 minus 2 to the 15 minus 1
long 8byte (-2)^63 ~ 2^63-1
byte 1byte – 128 ~ 127
float 4byte
double 8byte
boolean 1byte
char 2byte

Hotspot implements JVM rules to enable memory compression (64-bit machines) :

  • Below 4G, cut the high 32 places directly
  • 4 GB to 32 GB memory compression is enabled by default
  • Over 32G, compression is invalid, use 64 bits

So, bigger memory isn’t always better.

  1. Paddingalignment

This is aligned, this is aligned by multiples of 8. For 64-bit machines, it reads in blocks, not bytes, and each block holds multiple bytes of eight, so it has an alignment mechanism.

Allocation of bytes occupied by each part of array object memory:

  1. Object headmarkword8 bytes
  2. ClassPointerPointers, like normal objects, compress 4 bytes, uncompress 8 bytes
  3. The array length is 4 bytes
  4. An array of data
  5. Align multiples of 8

Count the number of bytes occupied by new Object()

Based on the above analysis, let’s verify the calculation results of the program written previously:

For the new Object ()

  • First of all,markwordAccount for8 bytes
  • ClassPointer: My machine has 8GB of memory, and the JVM has memory compression enabled by default, so ClassPointer takes up space4 bytes
  • Instance data: I just new an Object() without any reference type or expense type. This part takes no bytes
  • PaddingAlignment: front 8+4+0=12 bytes, needed here to satisfy multiples of 8A fillingto16 bytes

So, new Object() takes 16 bytes.

For new int [] {}

  • markword8 bytes:
  • ClassPointer: 4 bytes
  • The length of the array: 4 bytes
  • An array of data: 0 bytes
  • PaddingAlignment: 8+4+4+0=16, is already a multiple of 8, there is no need to align

Therefore, new int[]{} takes 16 bytes.

For my own definition of new P()

private static class P {
    // markword 8
/ / ClassPinter (4 - UseCompressedClassPointer 8; + UseCompressedClassPointer is 4)
/ / 4 int id;  // Oops 4 String name; // This is a reference to +UseCompressedOops 8 -UseCompressedOops 4/ / 1 byte b1; / / 1 byte b2;  //Oops 4  Object o; / / 8 long i; } Copy the code
  • markword8 bytes
  • ClassPointer4 bytes
  • The instance data:
    • Int 4 bytes
    • String references type 4 bytes
    • Two bytes 1*2=2 bytes
    • Object O Reference type 4 bytes
    • 8 bytes long
  • PaddingAlign: first calculate whether the multiple of 8 is satisfied 8+4+4+4+2+4+8=34, need to fill up the multiple of 8, fill up to 40

Therefore, new P() occupies 40 bytes in this example.

You can debug the program based on JVM parameters and get different results. The main parameters are as follows:

-XX:(+/-)UseCompressedClassPointers
-XX:(+/-))UseCompressedOops
Copy the code

Over. The above.


The first public line 100 li ER, welcome the old iron attention reading correction. GitHub github.com/xblzer/Java…