Accurately calculates the memory size occupied by a Java object

Source: Internet
Author: User

The article "Java Optimization Method for memory usage-traces of snow" mentions:

 

"What is the impression of a Java System? Memory usage! In this statement, more than N people stand up to defend Java and give a bunch of Performance Test reports to prove this. In theory, the Java System does not occupy more memory than the system developed in other languages. Why is there so many reasons to prove that it actually occupies the memory? Two characters, bad habits"

 

How can we measure the memory space occupied by objects? Some people may say that the following code is simple:

 

GC ();

Runtime. getruntime (). totalmemory ()-runtime. getruntime (). freememory ();

 

However, in this way, only the memory occupied by all instances in the heap can be calculated, and an object cannot be accurately calculated,

 

I wrote a small piece of code to calculate the memory usage of the object. The result is the same as the memory usage on my computer. The computer is configured with a 64-bit CPU and a 32-bit XP operating system, 32-bit sun Virtual Machine (parameter-client) with 3 GB memory, it is unclear whether the program is universal.

 

Algorithm Description:

1. The occupied size of value type variables is known

2. The reference type variable occupies 4 bytes (not tested in 64-bit JVM), for example, object x = NULL. This X variable occupies 4 bytes in 32-bit JVM.

3. Relationship between object size and occupied space: occupy = (size + 8-1)/8*8;

4. recursively traverse all member variables in an object, and the memory occupied by member variables,

 

(Currently, it is impossible to calculate the size of an object that contains members of the private java. Lang. Reflect. constructot type, because the value of this field of the object cannot be obtained through reflection ).

 

 

 

 

Import java. Lang. Reflect .*;

Import java. util .*;

 

// A reference: 4 bytes

// An object: 8 bytes

// An integer: 16 bytes = (8 + 4)/8*8

// An int: 4 bytes

// Array size 0: jro64 = 24, sun32 = 12

 

// Reference size, such as object = NULL: jro64 = jro32 = 4, sun32 = 4, sun64 = 8

// No member object size, such as new object ();: jro32 = jro64 = 8, sun32 = 8, sun64 = 16

// New byte [0]: jro32 = jro64 = 8 + 8 sun32 = 8 + 4, sun64 = 16 + 8

 

// Byte array of length L: (L + 19)/8*8

// Char/short array with a length of L: (L * 2 + 19)/8*8 = (L + 9)/4*8

// String with the length of L: (L + 1)/4*8 + 40

// Int array of length L: (L * 4 + 19)/8*8 = (L + 4)/2*8

// Long array of length L: (L * 8 + 19)/8*8 = (L + 2) * 8

Public class occupy {

 

// These eight methods cannot be written. Otherwise, occupyof (int x) will be automatically reloaded to occupyof (Object O) and cannot be determined in the method.

Public static int occupyof (Boolean variable ){

Return 1;

}

 

Public static int occupyof (BYTE variable ){

Return 1;

}

 

Public static int occupyof (short variable ){

Return 2;

}

 

Public static int occupyof (char variable ){

Return 2;

}

 

Public static int occupyof (INT variable ){

Return 4;

}

 

Public static int occupyof (float variable ){

Return 4;

}

 

Public static int occupyof (long variable ){

Return 8;

}

 

Public static int occupyof (double variable ){

Return 8;

}

 

Public occupy (byte nullreferencesize, byte emptyobjectsize, byte emptyarrayvarsize ){

This. null_reference_size = nullreferencesize;

This. empty_object_size = emptyobjectsize;

This. empty_array_var_size = emptyarrayvarsize;

}

 

Public static occupy forjrockitvm (){

Return new occupy (byte) 4, (byte) 8, (byte) 8 );

}

 

Public static occupy forsun32bitsvm (){

Return new occupy (byte) 4, (byte) 8, (byte) 4 );

}

 

Public static occupy forsun64bitsvm (){

Return new occupy (byte) 8, (byte) 16, (byte) 8 );

}

 

Public static occupy fordetectedvm (){

Return NULL;

}

 

Private Final byte null_reference_size;

Private Final byte empty_object_size;

Private Final byte empty_array_var_size;

 

Private Static class ref {

Public ref (Object OBJ ){

This. OBJ = OBJ;

}

Final object OBJ;

@ Override

Public Boolean equals (Object OBJ ){

Return (OBJ instanceof ref) & (REF) OBJ). OBJ = This. OBJ;

}

@ Override

Public int hashcode (){

Return obj. hashcode ();

}

}

 

Private list dedup = new arraylist ();

/**

* The memory space occupied by the object. the space occupied by the object is not equal to the size of the object, just like a file in Windows (4 K space occupied when the size is 1 byte)

* @ Param object

* @ Return

*/

Public int occupyof (Object object ){

Dedup. Clear ();

Return occupyof0 (object );

}

Private int occupyof0 (Object object ){

If (Object = NULL)

Return 0;

Ref r = new REF (object );

If (dedup. Contains (r ))

Return 0;

Dedup. Add (R );

Int varsize = 0; // The Value Type and reference type variable size in the object

Int objsize = 0; // The object instance size pointed to by the reference type in the object

For (class clazz = object. getclass (); clazz! = Object. Class; clazz = clazz. getsuperclass ()){

//

System. Out. println (clazz );

If (clazz. isarray () {// array of the current object

Varsize + = empty_array_var_size;

Class <?> Componenttype = clazz. getcomponenttype ();

If (componenttype. isprimitive () {// The current array is a native array.

Varsize + = lengthofprimitivearray (object) * sizeofprimitiveclass (componenttype );

Return occupyofsize (empty_object_size, varsize, 0 );

}

Object [] array = (object []) object;

Varsize + = null_reference_size * array. length; // The current array has length references, each occupying 4 bytes.

For (Object O: array)

Objsize + = occupyof0 (O );

Return occupyofsize (empty_object_size, varsize, objsize );

}

Field [] fields = clazz. getdeclaredfields ();

For (field: fields ){

If (modifier. isstatic (field. getmodifiers ()))

Continue; // The class member is not counted

// System. Out. println (field. getdeclaringclass ());

If (clazz! = Field. getdeclaringclass ())

Continue;

Class <?> Type = field. GetType ();

If (type. isprimitive ())

Varsize + = sizeofprimitiveclass (type );

Else {

Varsize + = null_reference_size; // a referenced variable occupies 4 bytes.

Try {

Field. setaccessible (true); // you can access non-public variables.

Objsize + = occupyof0 (field. Get (object ));

} Catch (exception e ){

Objsize + = occupyofconstructor (object, field );

}

}

}

}

Return occupyofsize (empty_object_size, varsize, objsize );

}

 

Public static int sizeof (Boolean variable ){

Return 1;

}

 

Public static int sizeof (BYTE variable ){

Return 1;

}

 

Public static int sizeof (short variable ){

Return 2;

}

 

Public static int sizeof (char variable ){

Return 2;

}

 

Public static int sizeof (INT variable ){

Return 4;

}

 

Public static int sizeof (float variable ){

Return 4;

}

 

Public static int sizeof (long variable ){

Return 8;

}

 

Public static int sizeof (double variable ){

Return 8;

}

 

/**

* Object size

* @ Param object

* @ Return

*/

Public int sizeof (Object object ){

If (Object = NULL)

Return 0;

Int size = empty_object_size;

Class clazz = object. getclass ();

If (clazz. isarray ()){

Size + = empty_array_var_size; // The length variable is of the int type.

Class <?> Componenttype = clazz. getcomponenttype ();

If (componenttype. isprimitive ())

Return size + lengthofprimitivearray (object) * sizeofprimitiveclass (componenttype );

Object [] array = (object []) object;

Size + = 4 * array. length;

For (Object O: array)

Size + = sizeof (O );

Return size;

}

Field [] fields = clazz. getdeclaredfields ();

For (field: fields ){

If (modifier. isstatic (field. getmodifiers ()))

Continue; // The class member is not counted

Class <?> Type = field. GetType ();

If (type. isprimitive ())

Size + = sizeofprimitiveclass (type );

Else {

Size + = 4; // a referenced variable occupies 4 bytes

Try {

Field. setaccessible (true); // you can access non-public variables.

Size + = sizeof (field. Get (object ));

} Catch (exception e ){

Size + = sizeofconstructor (object, field );

}

}

}

Return size;

}

 

Private Static int occupyofconstructor (Object object, field ){

Throw new unsupportedoperationexception ("Field Type constructor not accessible:" + object. getclass () + "field:" + field );

}

 

Private Static int sizeofconstructor (Object object, field ){

Throw new unsupportedoperationexception ("Field Type constructor not accessible:" + object. getclass () + "field:" + field );

}

 

/**

* The object size and occupied space are not equal, just like files in Windows (4 K space when the size is 1 byte)

* The increase in the space occupied by objects is measured in 8 bytes. the space occupied is equal to the unconditional carry-on Method for 8 bytes,

* Occupy = (size + 8-1)/8*8; for example:

* 8-byte size: 8 bytes occupied. (new object () means 8 bytes occupied)

* 9 Bytes: 16 bytes

* Size: 16 bytes

* 17 Bytes: 24 bytes

* @ Param size, in bytes

* @ Return space occupied

*/

Private Static int occupyofsize (INT size ){

Return (size + 7)/8*8;

}

 

Private Static int occupyofsize (INT selfsize, int varssize, int objssize ){

// System. Out. println ("Self =" + selfsize + "vars =" + varssize + "objs =" + objssize );

Return occupyofsize (selfsize) + occupyofsize (varssize) + objssize;

}

 

Private Static int sizeofprimitiveclass (class clazz ){

Return clazz = Boolean. Class | clazz = byte. Class? 1: clazz = Char. Class | clazz = short. Class? 2: clazz = int. Class | clazz = float. Class? 4

: 8;

}

 

Private Static int lengthofprimitivearray (Object object ){

Class <?> Clazz = object. getclass ();

Return clazz = Boolean []. Class? (Boolean []) object). Length: clazz = byte []. Class? (Byte []) object). Length

: Clazz = char []. Class? (Char []) object). Length: clazz = short []. Class? (Short []) object). Length

: Clazz = int []. Class? (INT []) object). Length: clazz = float []. Class? (Float []) object). Length

: Clazz = long []. Class? (Long []) object). Length: (double []) object). length;

}

}

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.