在開發過程中,我們有時需要來擷取某個對象的大小,以友善我們參考,來決定開發的技術方案。jvm中提供了兩種方式來擷取一個對象的大小。
編寫計算代碼:
其中sizeof方法僅僅擷取的是目前對象的大小,而該對象的如果存在對其他對象的引用,則不在計算範圍以内,而fullsizeof則會計算整體的大小。
将該java檔案進行編譯,并打成jar包
com.java.basic.SizeOfAgent .java
jar cvf sizeOfAgent.jar com/java.basic/SizeOfAgent .class
修改META-INF/MANIFEST.MF檔案内容
Premain-Class: com.java.basic.SizeOfAgent
Boot-Class-Path:
Can-Redefine-Classes: false
注意:每個冒号後面都有一個空格,且最後一行會有一個換行
将該jar包導入項目
添加啟動參數:-javaagent:E:\sizeOfAgent.jar
我這邊是将該jar包放在e盤,這裡填寫絕對路徑。
這樣我們就可以通過調用該類中的sizeOf方法或者fullSizeOf方法即可。
unsafe對象可以擷取到一個對象中各個屬性的記憶體指針的偏移量,可以利用其來計算一個對象的大小。
當我們需要計算一個對象大小時,我們隻需要擷取ClassIntrospector執行個體,并調用其introspect方法,參數為需要計算大小的對象,就可以擷取到ObjectInfo對象,這個對象中就包含了要計算的對象的各項資訊(名字,類型,屬性的偏移量等),想要擷取對象的大小,我們隻需要調用OjbectInfo的getDeepSiz即可。
ClassIntrospector中還定義了一個方法getObjectRefSize,這個方法的作用是擷取目前虛拟機對象引用指針所占的空間,如果機器的記憶體在32G以下,則會預設開啟指針壓縮,占4個位元組,否則占8個,可以使用參數-XX:-UseCompressedOops進行指針壓縮
首先我們先定義一個對象:
測試代碼:
運作結果:
兩種方法的運作結果一緻,我們進行對象的手動計算,計算公式:
mark頭(8位元組)+oop指針(4位元組)+對象屬性
以person對象為例:
mark頭(8位元組)+oop指針(4位元組)+name(String類型引用4位元組)+age(int類型引用4位元組)=20
jvm會對一個對象進行記憶體對齊,是的對象的大小為8的倍數,是以最終結果為24。
當然這兩種計算方式都是對對象的一個大概計算,當一個對象引用String類型時,其實是有常量池的存在的,是以計算出來的隻我們隻能做個參考即可。