你知道資料大小嗎?--不要花太多的功夫來隱藏類的成員(二) (轉)
結果::namespace prefix = o ns = "urn:schemas--com::office" />
讓我們來對一些類使用這個工具,察看是否結果和我們預想的一樣。
注意:以下的結果都是基於平臺的1.3.1版本,並不能保證所有的平臺或者jdk版本都得到相同的資訊。
l .lang.
這個所有的基類作為我們的第一個例子。對於java.lang.Object我們將得到:
'before' heap: 510696, 'after' heap: 1310696
heap delta: 800000, {class java.lang.Object} size = 8 bytes
所以,一個簡單的Object物件要佔用8個位元組的空間,當然我們不能希望它所佔的空間是0,因為每個例項都至少必須包含一些最基本的操作,比如equals(), hashCode(), wait()/notify()等。
l java.lang.Integer
我和我的同事都經常封裝本地的int到Integer的例項中去,以便於我們能在集合的物件中使用它們,那樣做到底要耗費多少記憶體呢?
'before' heap: 510696, 'after' heap: 2110696
heap delta: 1600000, {class java.lang.Integer} size = 16 bytes
這個16位元組的結果比我們預想的要糟糕,因為一個int值恰好是4個位元組,但是使用了Integer以後,多使用了3倍的空間。
l java.lang.Long
Long看起來應該比Integer使用更多的空間,可是事實並非如此:
'before' heap: 510696, 'after' heap: 2110696
heap delta: 1600000, {class java.lang.Long} size = 16 bytes
很明顯,因為一種特別的JVM實現必須符合特定的型別,所以事實上的物件大小在堆中所佔的空間必須和低階的記憶體邊界對齊。看起來一個Long是一個8位元組的大小的Object物件加上8位元組用來儲存long值。相比之下,Integer就有4個位元組沒有使用的空間。所以,應該是JVM強制物件使用8位元組作為字的邊界。
l Arrays
接下來比較一些基本型別的陣列,比較有指導意義,能夠部分的發現一些隱藏的資訊和證明另一些流行的詭計:使用一個size-1的陣列封裝基本型別來當作物件。透過修改Sizeof.main()來使用一個迴圈增加陣列的長度。然後能夠得到int陣列:
length: 0, {class [I} size = 16 bytes
length: 1, {class [I} size = 16 bytes
length: 2, {class [I} size = 24 bytes
length: 3, {class [I} size = 24 bytes
length: 4, {class [I} size = 32 bytes
length: 5, {class [I} size = 32 bytes
length: 6, {class [I} size = 40 bytes
length: 7, {class [I} size = 40 bytes
length: 8, {class [I} size = 48 bytes
length: 9, {class [I} size = 48 bytes
length: 10, {class [I} size = 56 bytes
還有一些char陣列:
length: 0, {class [C} size = 16 bytes
length: 1, {class [C} size = 16 bytes
length: 2, {class [C} size = 16 bytes
length: 3, {class [C} size = 24 bytes
length: 4, {class [C} size = 24 bytes
length: 5, {class [C} size = 24 bytes
length: 6, {class [C} size = 24 bytes
length: 7, {class [C} size = 32 bytes
length: 8, {class [C} size = 32 bytes
length: 9, {class [C} size = 32 bytes
length: 10, {class [C} size = 32 bytes
從以上可以看出,8個位元組的邊界很明顯的表現出來了。同時,肯定包含不可避免的8個位元組的Object頭部,然後基本資料型別的陣列佔用其它的8個位元組。使用int[1]和Integer相比,看起來不能提供任何的記憶體使用,除了可以作為一個同樣資料的可變版本。
l 多維陣列
多維陣列有另外的一個驚人之處。開發者普遍的使用一個構造例如int[dim1][dim2]用於數字或者科學計算。在一個int[dim1][dim2]的陣列例項中,每一個巢狀的int[dim2]都是一個物件,並且每一個物件都加上一個16位元組的陣列物件頭。當我不需要一個三角的或者粗糙的陣列,那個代表著純粹的頭部。當維數增加時,影響增加很大。舉例來說,一個int[128][2]的例項佔用3600位元組,使用著246%的頭部。在特別的例子byte[256][1]中,這個頭部因素已經是19!和C/C++的解決方案相比,同樣的語法不會增加這麼多的記憶體消耗。
l java.lang.String
讓我們來測試一個空串,現構造一個new String():
'before' heap: 510696, 'after' heap: 4510696
heap delta: 4000000, {class java.lang.String} size = 40 bytes
結果提供了一種相當不好的現象,就是一個空的String就要佔用40位元組的大小,足夠用來儲存20個字元了。
在我們使用包含內容的字串以前,我們使用一個幫組方法來建立一個字串。不過使用以下文字來建立:
object = "string with 20 chars";
將不會工作,因為所有的這樣的物件操作將結束於同一個字串例項。語言規範中明確表明如此的行為(java.lang.String.intern()),因此使用如下:
public static String createString (final int length)
{
char [] result = new char [length];
for (int i = 0; i < length; ++ i) result [i] = (char) i;
return new String (result);
}
在這樣的建立函式以後,得到如此的結果:
length: 0, {class java.lang.String} size = 40 bytes
length: 1, {class java.lang.String} size = 40 bytes
length: 2, {class java.lang.String} size = 40 bytes
length: 3, {class java.lang.String} size = 48 bytes
length: 4, {class java.lang.String} size = 48 bytes
length: 5, {class java.lang.String} size = 48 bytes
length: 6, {class java.lang.String} size = 48 bytes
length: 7, {class java.lang.String} size = 56 bytes
length: 8, {class java.lang.String} size = 56 bytes
length: 9, {class java.lang.String} size = 56 bytes
length: 10, {class java.lang.String} size = 56 bytes
結果很明顯的表明了字串的記憶體增加軌跡。但是字串要增加一個24位元組的頭部。對於非空的字串,如果字元個數少於10個或者更少,這個增加的頭部將消耗相對於有效的負載(2個位元組對於每個字元,加上4個作為長度)在100%到400%之間變化。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-998547/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 你知道資料大小嗎?--不要花太多的功夫來隱藏類的成員(三) (轉)
- 你知道資料大小嗎?--不要花太多的功夫來隱藏類的成員(一) (轉)
- 蘋果mac隱藏的神技能,你都知道嗎蘋果Mac
- 超好用的macOS Monterey 隱藏功能,這些你都知道嗎Mac
- 類成員函式的重寫,過載和隱藏的區別函式
- 隱藏的資料夾怎麼找出來 恢復隱藏資料夾的辦法
- ABAP Code Inspector那些隱藏的功能,您都知道嗎?
- Python中你所不知道的“隱藏技巧”!Python
- win10隱藏的資料夾怎麼找出來 顯示隱藏資料夾步驟Win10
- iOS 8的這十項隱藏功能 你都知道麼?iOS
- 你知道資料庫索引的工作原理嗎?資料庫索引
- 依據類的成員來對類進行排序的泛型方法 (轉)排序泛型
- 你知道的反射是這樣嗎?(二)反射
- 你可能不知道的 10 個 Laravel Eloquent 的隱藏特性Laravel
- 隱藏資料夾怎麼取消隱藏 關閉隱藏檔案的辦法
- C++ 成員函式的過載,繼承,覆蓋和隱藏C++函式繼承
- EXCEL你不知道的三個秘密:沒想到隱藏的這麼深Excel
- 你可能不知道的10個CSS3中的隱藏特性CSSS3
- 資料隱藏技術資料隱藏
- iOS 9正式釋出,你發現其中隱藏的功能了嗎iOS
- 作為開發人員,這四類Code Review方法你都知道嗎?View
- 你知道MySQL是如何處理千萬級資料的嗎?MySql
- win10資料夾如何隱藏_win10系統的資料夾怎麼隱藏Win10
- 資料夾的隱藏(十)終極篇
- Notes隱藏資料庫設計應用的維護 (轉)資料庫
- CWinApp類成員 (轉)APP
- 二哥,你知道騰訊的技術職級嗎?
- 移動端動態化的由來,你知道嗎?
- 你知道Ctrl+Alt+Delete是怎麼來的嗎?delete
- win10 如何顯示隱藏資料夾_win10 如何顯示隱藏的資料夾Win10
- win10如何顯示隱藏資料夾 win10開啟隱藏資料夾的方法Win10
- 這些著名資料庫之間的“關係”,你知道嗎?資料庫
- 你知道嗎?常用的資料探勘分析工具Mahout和MLlib
- win10怎樣顯示隱藏的資料夾_win10隱藏檔案怎麼顯示出來Win10
- 隱藏資料夾怎麼顯示出來win10 win10怎麼開啟隱藏的檔案Win10
- GRUB選單隱藏的解除(轉)
- 刪除WinXP隱藏的元件(轉)元件
- win10怎麼顯示隱藏資料夾 win10顯示隱藏資料夾的方法Win10