Java中計算物件的大小
一、計算物件大小的方法
Java中如何計算物件的大小呢,找到了4種方法:
1.java.lang.instrument.Instrumentation的getObjectSize方法;
2.BTraceUtils的sizeof方法;
本質上java.lang.instrument.Instrumentation的使用是其他三種方法的基礎,但是該類中的方法getObjectSize只是計算了物件本身,JDK註釋描述:
Returns an implementation-specific approximation of the amount of storage consumed by
the specified object. The result may include some or all of the object's overhead,
and thus is useful for comparison within an implementation but not between implementations.
第2種是使用BTrace的方法,可以對生產環境的程式進行檢測,但是BTraceUtils的sizeof實現上直接呼叫的還是java.lang.instrument.Instrumentation的getObjectSize方法,所以還是存在第1種方法的問題。第3中方法可以計算陣列的大小,但是無法計算HashMap等物件。第4種方法支援對HashMap等常見物件的大小計算。
第1種方法網上可以找到很多資料可以參考,第3中方法連結博文內容已經很詳細。這裡給出第2中方法以及第4種方法的使用步驟。
二、BTrace中計算物件大小
我使用的BTrace是Java VisualVM中的外掛版。VisualVM開啟方式為命令列輸入jvisualvm,
安裝外掛BTrace,安裝成功的話,檢視Plugin視窗
安裝外掛這部分工作這裡就不說了,下面演示如何使用。
啟動tomcat,在VisualVM左側中選擇剛剛啟動的tomcat,右鍵彈框中選擇Trace application
這時右側將會開啟BTrace視窗:
上面右側程式碼是BTrace用於檢測com.test.data.TestBtrace類在執行search方法後返回值的大小。
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*; @BTrace public class Sizeof { @OnMethod( clazz="com.test.data.TestBtrace", method = "search", location = @Location(Kind.RETURN) ) public static void onnew(@Return Object obj) { println(Strings.concat("object of: ", Reflective.name(Reflective.classOf(obj)))); println(Strings.concat("size: ", Strings.str(sizeof(obj)))); } }
點選start按鈕執行成功顯示如下(紅框內),說明已經進入監視狀態:
執行tomcat上面的com.test.data.TestBtrace中search方法,BTrace控制檯打印出了返回結果物件的型別以及物件大小,每次都是48 bytes。
其中docs有幫助文件,samples有例子。
三、使用MemoryMeasurer計算物件大小
到https://github.com/mingbozhang/memory-measurer上面將原始碼下載到本地,編譯需要本地預先安裝java,maven。
1.加入檢測程式碼到目的碼中
這裡的使用方法不像BTrace的低侵入,需要在程式碼中加入檢測程式碼:
long memory = MemoryMeasurer.measureBytes(objectToTest);
通過輸出日誌或者其他方式將上面程式碼中變數memory內容獲取到。
2.啟動TOMCAT是在JAVA_OPTS中加入:
-javaagent:<實際目錄>/memory-measurer-0.1.0-SNAPSHOT.jar
3.啟動TOMCAT,操作application並檢視打印出的待檢測物件的大小資訊。
使用該方法測試出的com.test.data.TestBtrace中search方法返回結果物件大小為:349264 bytes
注意:由於此專案依賴guava包,如果待測試程式碼直接main方法啟動使用target生成的memory-measurer-0.1.0-SNAPSHOT.jar,如果是檢測tomcat上的application則需要使用target生成的memory-measurer-0.1.0-SNAPSHOT-jar-with-dependencies.jar。
四、思考
找到的這幾種方法第1、2中是比較官方一些的方法。3、4是個人寫的程式碼或者工具。如果尋找容器物件真實大小這個需求是個迫切需求,為什麼沒有看到官方版本的物件真實大小計算工具?