Java object instance size differs in different JVMs

Here I found that the instance size of the same class is not the same in another version of the JVM (it is 40 in 1.6.0_21 and 24 in 1.6.0_31 ). although the code is the same. Who do you come across before? Or do you have any suggestions?

JDK 1.6.0_21

# java -version java version "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b06) Java HotSpot(TM) 64-Bit Server VM (build 17.0-b16, mixed mode) # java obj.ObjectSize & # jps | grep ObjectSize 27251 ObjectSize # jmap -histo 27251 | grep US_ASCII 145: 1 40 sun.nio.cs.US_ASCII 

JDK 1.6.0_31

 # java -version java version "1.6.0_31" Java(TM) SE Runtime Environment (build 1.6.0_31-b04) Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode) # java obj.ObjectSize & # jps | grep ObjectSize 26645 ObjectSize # jmap -histo 26645 | grep US_ASCII 161: 1 24 sun.nio.cs.US_ASCII 

ObjectSize.java

 package obj; import java.util.concurrent.TimeUnit; import sun.nio.cs.US_ASCII; public class ObjectSize { public static void main(String[] args) { US_ASCII as = new US_ASCII(); System.out.println(as); try { TimeUnit.MINUTES.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 
+4
source share
3 answers

I think that you are confronted with a fact related to how compiled programming languages ​​work, especially if they work inside a virtual machine.

Changes in the implementation of virtual machines allow you to behave differently, for example. By creating Java-byte code of different sizes - as long as it supports the same Java API.

Is the difference in memory usage really that big? If memory expansion is actually a problem, I would dare to suggest that you already had a memory problem in the first place.

If you worked at 50% capacity with one virtual machine and now click on the cap on the other, I think you need to take some deeper changes in your code. Or throw more hardware at the problem .;)

+5
source

Earlier versions of supported Java 6 -XX:+UseCompressedOops , but this was disabled by default. (The first versions of Java 6 did not support this at all) This means that the links in the 64-bit JVM were 64-bit. The new JVM uses a 32-bit link if the heap is <32 GB. He can do this, since obejcts are 8-byte aligned, so you can address 2 ^ 32 * 8 bytes with a 32-bit link.

Note: US_ASCII inherits three fields from Charset.

 private final String name; // tickles a bug in oldjavac private final String[] aliases; // tickles a bug in oldjavac private Set<String> aliasSet = null; 

These links are reduced by 4 bytes, saving 12 bytes, however objects are aligned by 8 bytes, so the total storage is 16 bytes.

Using compressed oops reduces the amount of memory used.

Compress oops in JVM Hotspot

BTW: you would not use this class directly, instead you would use StandardCharset.US_ASCII

+2
source

Do you have any suggestions?

If memory usage is important to you, do not use the 64-bit version 1.6.0_21. Switch to the 32-bit version or to a newer fix level. Or better yet, Java 7. After all, 1.6.0_21 is VERY deprecated.

Alternatively, run the JVM with the option of explicitly enabling compressed oops, as described here :

"For JDK 6, before the release of 6u23, use the -XX: + UseCompressedOops flag with the java command to enable this function."

(But beware that this can tickle errors in what was ... at that time ... another experimental JVM function.)

+1
source

All Articles