JAVA使用SizeOf


研究一下JAVA的SizeOf

引用外部類實現JAVA的SizeOf

JAVA本身是沒有SizeOf的,因此我們需要去MavenRepository中下載JAR包(也可以使用maven等),因為這里只是做一個簡單測試,就直接下載了JAR包。

點擊jar下載,最新的版本也是2015年,算是比較老了。

下載成功后導入自己的JAVA項目,具體怎么導入網上有很多教程,就不贅述了。

可以看到我這里已經引用成功了,import后可以直接使用這些類了。

簡單的測試

接下來來做一些簡單的測試,看看這個類提供的sizeOf方法是否准確。

System.out.println(RamUsageEstimator.sizeOf(new Object()));

在控制台我們可以看到輸出的結果是16。

可能還有人不清楚為什么會是16,這邊給出一個鏈接,可以學習一下,個人覺得還是挺有幫助的。

Object存儲內容

Integer等也都可以測試一下,結果還是很正確的。

那比較重要的就是數組和對象中再包含對象的,能否還是比較精確呢?

我們先來寫一個簡單的對象。

先給出一些例子,大家想想是為什么。

import com.carrotsearch.sizeof.RamUsageEstimator;

public class SizeOfTest {
    public static void main(String[] args) {
        System.out.println(RamUsageEstimator.sizeOf(new MemTest()));
    }
}

class MemTest{
    Integer a = 12;
}

結果是32,其實挺好解釋的,MemTest本身和Object對象一樣,占用12字節,a這個引用在指針壓縮后占用4字節,加上a的16,自然是32。

我們把Integer改成int,結果答案還是16。

再加上一個int b,就變成了24。這是因為指針對齊。

如果你剛才有仔細去研究那個鏈接的話,你會看到Object本來應該占12個字節的,只是為了對齊變成了16。加上一個int的4字節,剛好是16。但我們改成Integer a;發現結果也是16。難道a不應該是8個字節的地址的引用嗎?可以去了解一下指針壓縮,默認是開啟的,因此占用四個字節。

這樣就可以解釋的通了,再多做幾次測試,加上各種各樣的對象,也是這樣的,符合我們計算出來的值。

再測試一種比較有意思的情況:

這種情況顯示的是40。

這種情況卻是56。

這是因為Java在處理Integer時使用了一個緩存,其中緩存了-128到127之間的數字對應的Integer對象。

看來源碼應該不是簡單的相加。(還沒來得及研究源碼)

這里插一個鏈接:https://blog.csdn.net/weixin_35204634/article/details/113451805?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control&dist_request_id=1328741.39129.16169961773027181&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-1.control

對研究JAVA內存結構很有幫助。

研究數組的情況

接下來來研究一下數組的測試是否准確,數組占用空間之前應用RunTime下提供的jvm內存判斷的工具測試過,但那種方法不太准確,只能通過加大數組中元素個數來測試一個JAVA對象占用空間(所以Object一個對象占16字節我是測試過的!感興趣的人可以看這個網址https://blog.csdn.net/ithomer/article/details/7310008)。同時還得出了結論,int[2][1024*1024]占用的內存比int[1024*1024][2]要小得多,這個也很好理解,JAVA的二維數組其實就是以數組為元素的數組,數組中自然有描述的一些東西,數組越多自然占用空間越大。

其實一維數組的情況不難,一維數組就相當於一個對象頭+一片數組數據空間。

這里要注意:數組的對象頭是這樣的,MarkWord占用8字節,Class Point占用4字節,Length 數組占用4字節。

比如int[1]就是8+4+4+4,再對齊,就是24,測試發現相符。

那二維數組呢,我們先理論分析一下,以int[2][2]為例,先從二維的角度來看,對象頭應該是16個字節,兩個一維的指針一共8字節,兩個一維數組各自如上占用24字節。也就是16+8+48=72字節,驗證一下,果不其然。

總結

對這個SizeOf的測試就到此為止啦,主要是精確度的測試,結合網上查到的資料,精確度應該還行。

JAVA的內存實在太復雜了,方法區,棧內存,特別是常量池又分為了好幾種。。。了解的不夠透徹,陷入了好幾次圈圈中,查了好多資料才了解,因此決定也發個博客回饋一下。

之后准備測試一下比較復雜的情況下的精確度和效率。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM