java對象的內存佈局(一):計算java對象佔用的內存空間以及java object layout

最近在學習java對象內存佈局方面的一些知識,主要是想知道一個java對象到底佔 用多少內存空間,以及java對象在內存中究竟是什麼樣子的。c/c++中的sizeof運算符可以方便地告訴咱們一個變量佔用的內存空間,可是在 java中卻沒有直接提供這種機制。若是想獲取java對象佔用的內存大小,能夠利用java的Instrumentation機制。 java.lang.instrument.Instrumentation這個接口提供了getObjectSize(Object objectToSize),可以告訴咱們一個對象的大小。如何獲取Instrumentation對象,網上有不少資料,這裏再也不贅述。 html

[java] view plain copy
  1. public static void main(String[] args)  
  2. {  
  3.     // 經過pre-agent獲取Instrumentation對象  
  4.     Instrumentation instr = AgentGetter.getInstrumentation();  
  5.           
  6.     System.out.println(instr.getObjectSize(new Object()));  
  7. }  

Java對象的內存佈局:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)。不管是32位仍是64位的HotSpot,使用的都是8字節對齊。 也就是說每一個java對象,佔用的字節數都是8的整數倍。(對象頭 + 實例數據 + padding) % 8等於0且0 <= padding < 8。在網上看到各類介紹如何手動計算對象大小的文章,總結了幾點:

1.基本數據類型佔用的字節數,JVM規範中有明確的規定,不管是在32位仍是64位的虛擬機,佔用的內存大小是相同的。
2.reference類型在32位JVM下佔用4個字節,可是在64位下可能佔用4個字節或8個字節,這取決因而否啓用了64位JVM的指針壓縮參數UseCompressedOops。
3.new Object()這個對象在32位JVM上佔8個字節,在64位JVM上佔16個字節。
4.開啓(-XX:+UseCompressedOops)指針壓縮,對象頭佔12字節; 關閉(-XX:-UseCompressedOops)指針壓縮,對象頭佔16字節。
5.64位JVM上,數組對象的對象頭佔用24個字節,啓用壓縮以後佔用16個字節。之因此比普通對象佔用內存可能是由於須要額外的空間存儲數組的長度。
6.對象內存佈局中的實例數據,不包括類的static字段的大小,由於static字段是屬於類的,被該類的全部對象共享。
java

關於對象內存佈局的計算規則,能夠參考這篇文章講的很詳細"Java對象內存結構"。 c++


更具體的能夠參考「一個Java對象到底佔用多大內存?」這篇文章。在網上搜索的過程當中看到了java object layout這個小工具,可以打印出類的佈局信息。 bootstrap

項目的主頁是:http://openjdk.java.net/projects/code-tools/jol/ 數組

項目代碼在http://central.maven.org/maven2/org/openjdk/jol/ 安全


下載jol-core-0.3.2.jar以後,將其加入項目的build path,經過下面的代碼就能夠查看某個類的佈局信息。 maven

[java] view plain copy
  1. package jol;  
  2.   
  3. import org.openjdk.jol.info.ClassLayout;  
  4. import org.openjdk.jol.util.VMSupport;  
  5.   
  6.   
  7.   
  8. public class T1 {  
  9.   
  10.     public static void main(String[] args) throws Exception {  
  11.           
  12.         System.out.println(VMSupport.vmDetails());  
  13.           
  14.         System.out.println(ClassLayout.parseClass(VO.class).toPrintable());  
  15.     }  
  16.   
  17. }  
運行這段代碼,能夠看到jol輸出以下信息:

[plain] view plain copy
  1. Running 64-bit HotSpot VM.  
  2. Objects are 8 bytes aligned.  
  3. Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]  
  4. Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]  
  5.   
  6. jol.VO object internals:  
  7.  OFFSET  SIZE  TYPE DESCRIPTION                    VALUE  
  8.       0    16       (object header)                N/A  
  9.      16     8  long VO.b                           N/A  
  10.      24     4   int VO.a                           N/A  
  11.      28     4       (loss due to the next object alignment)  
  12. Instance size: 32 bytes (estimated, the sample instance is not available)  
  13. Space losses: 0 bytes internal + 4 bytes external = 4 bytes total  
能夠看到jol工具,可以顯示出對象頭的大小,以及每一個實例字段的偏移,進而計算對象佔用的內存大小。

jol工具還提供了一個命令行工具jol-cli-0.3.2-full.jar,包含了main方法可以直接在命令行運行,查看類的佈局信息。能夠從這裏下載jol-cli工具。

[plain] view plain copy
  1. #查看jdk系統類的佈局信息  
  2. >java -jar jol-cli-0.3.2-full.jar internals java.lang.Object  

[plain] view plain copy
  1. #若是咱們本身的jar放在C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\下,那麼會自動加載;  
  2. #若是咱們本身的jar放在C:\Program Files\Java\jdk1.7.0_80\jre\lib\下,那麼不會自動加載(多是由於安全問題#,bootstrap類加載器僅僅加載jdk的核心類);  
  3. >java -jar jol-cli-0.3.2-full.jar internals net.aty.VO  


[plain] view plain copy
  1. #方式1:指定classpath,查看本身的類佈局  
  2. >java -jar jol-cli-0.3.2-full.jar internals -cp mydemo.jar net.aty.VO  


[plain] view plain copy
  1. #方式2:指定classpath,查看本身的類佈局  
  2. >java -cp mydemo.jar;jol-cli-0.3.2-full.jar org.openjdk.jol.Main internals net.aty.VO  

上面幾種方式都可以正確運行,可是下面這種方式是錯誤的,會報錯ClassNotFoundException。

[plain] view plain copy
  1. #注意:這種方式會報錯:java.lang.ClassNotFoundException:  
  2. #這是由於:若是採用了-jar參數來運行可執行的jar包,JVM會忽略你設置的classpath以及全部環境變量  
  3. java -cp mydemo.jar -jar jol-cli-0.3.2-full.jar internals net.aty.VO 


http://blog.csdn.net/aitangyong/article/details/46416667 工具

相關文章
相關標籤/搜索