1. 程式人生 > >一個物件佔用多大記憶體

一個物件佔用多大記憶體

物件頭

物件頭在32位系統上佔用8bytes,64位系統上佔用16bytes。

例項資料

原生型別(primitive type)的記憶體佔用如下:

Primitive Type Memory Required(bytes)
boolean 1
byte 1
short 2
char 2
int 4
float 4
long 8
double 8

reference型別在32位系統上每個佔用4bytes, 在64位系統上每個佔用8bytes。

對齊填充

HotSpot的對齊方式為8位元組對齊:

(物件頭 + 例項資料 + padding) % 8等於0且0 <= padding < 8

指標壓縮

物件佔用的記憶體大小收到VM引數UseCompressedOops的影響。

1)對物件頭的影響

開啟(-XX:+UseCompressedOops)物件頭大小為12bytes(64位機器)。

static class A {
        int a;
    }

A物件佔用記憶體情況:

關閉指標壓縮: 16+4=20不是8的倍數,所以+padding/4=24

開啟指標壓縮: 12+4=16已經是8的倍數了,不需要再padding。

1) 對reference型別的影響

64位機器上reference型別佔用8個位元組,開啟指標壓縮後佔用4個位元組。

static
class B2 { int b2a; Integer b2b; }

B2物件佔用記憶體情況:

關閉指標壓縮: 16+4+8=28不是8的倍數,所以+padding/4=32

開啟指標壓縮: 12+4+4=20不是8的倍數,所以+padding/4=24

陣列物件

64位機器上,陣列物件的物件頭佔用24個位元組,啟用壓縮之後佔用16個位元組。之所以比普通物件佔用記憶體多是因為需要額外的空間儲存陣列的長度。

先考慮下new Integer[0]佔用的記憶體大小,長度為0,即是物件頭的大小:

未開啟壓縮:24bytes

開啟壓縮後:16bytes

接著計算new Integer[1],new Integer[2],new Integer[3]和new Integer[4]就很容易了:

未開啟壓縮:

開啟壓縮:

拿new Integer[3]來具體解釋下:

未開啟壓縮:24(物件頭)+8*3=48,不需要padding;

開啟壓縮:16(物件頭)+3*4=28,+padding/4=32,其他依次類推。

自定義類的陣列也是一樣的,比如:

static class B3 {
        int a;
        Integer b;
    }

new B3[3]佔用的記憶體大小:

未開啟壓縮:48

開啟壓縮後:32

複合物件

計算複合物件佔用記憶體的大小其實就是運用上面幾條規則,只是麻煩點。

1)物件本身的大小

直接計算當前物件佔用空間大小,包括當前類及超類的基本型別例項欄位大小、引用型別例項欄位引用大小、例項基本型別陣列總佔用空間、例項引用型別陣列引用本身佔用空間大小; 但是不包括超類繼承下來的和當前類宣告的例項引用欄位的物件本身的大小、例項引用陣列引用的物件本身的大小。

static class B {
        int a;
        int b;
    }
static class C {
        int ba;
        B[] as = new B[3];

        C() {
            for (int i = 0; i < as.length; i++) {
                as[i] = new B();
            }
        }
    }

未開啟壓縮:16(物件頭)+4(ba)+8(as引用的大小)+padding/4=32

開啟壓縮:12+4+4+padding/4=24

2)當前物件佔用的空間總大小

遞迴計算當前物件佔用空間總大小,包括當前類和超類的例項欄位大小以及例項欄位引用物件大小。

遞迴計算複合物件佔用的記憶體的時候需要注意的是:對齊填充是以每個物件為單位進行的,看下面這個圖就很容易明白。

現在我們來手動計算下C物件佔用的全部記憶體是多少,主要是三部分構成:C物件本身的大小+陣列物件的大小+B物件的大小。

未開啟壓縮:

(16 + 4 + 8+4(padding)) + (24+ 8*3) +(16+8)*3 = 152bytes

開啟壓縮:

(12 + 4 + 4 +4(padding)) + (16 + 4*3 +4(陣列物件padding)) + (12+8+4(B物件padding))*3= 128bytes

大家有興趣的可以試試。

實際工作中真正需要手動計算物件大小的場景應該很少,但是個人覺得做為基礎知識每個Java開發人員都應該瞭解,另外:對自己寫的程式碼大概佔用多少記憶體,記憶體中是怎麼佈局的應該有一個直覺性的認識。

相關推薦

一個物件佔用記憶體

物件頭 物件頭在32位系統上佔用8bytes,64位系統上佔用16bytes。 例項資料 原生型別(primitive type)的記憶體佔用如下: Primitive Type Memory Required(bytes) boolean 1 byte 1 short 2 char

高端面試必備:一個Java物件佔用記憶體

這個問題一般會出現在稍微高階一點的 Java 面試環節。要求面試者不僅對 Java 基礎知識熟悉,更重要的是要了解記憶體模型。 #### Java 物件模型 HotSpot JVM 使用名為 oops (Ordinary Object Pointers) 的資料結構來表示物件。這些 oops 等同於本地

百度開源分散式id生成器uid-generator原始碼剖析 偽共享(false sharing),併發程式設計無聲的效能殺手 一個Java物件到底佔用記憶體? 寫Java也得了解CPU--偽共享

百度uid-generator原始碼 https://github.com/baidu/uid-generator   snowflake演算法 uid-generator是基於Twitter開源的snowflake演算法實現的。 snowflake將long的64位分為了3部分,時間戳、

百度uid-generator原始碼 偽共享(false sharing),併發程式設計無聲的效能殺手 一個Java物件到底佔用記憶體? 寫Java也得了解CPU--偽共享

https://github.com/baidu/uid-generator   snowflake演算法 uid-generator是基於Twitter開源的snowflake演算法實現的。 snowflake將long的64位分為了3部分,時間戳、工作機器id和序列號,位數分配如下。

一個Java物件到底佔用記憶體

在進行 JVM 調優時,我們經常關注 JVM 各個區域大小以及相關引數,從而進行特定的優化,在一次排查記憶體溢位問題時我不禁想到一個問題,一個 Java 物件到底佔用多大記憶體?下面我們就來分析驗證下。 Java 物件記憶體結構 在 JVM 中,Java 物件都是在堆記憶體上分配的,想要分析出 Java

一張100px*100px的圖片在記憶體中會佔用記憶體

    轉: http://www.cnblogs.com/YuangPong/p/6694512.html   在實際開發當中我們經常會忽視如題問題,只是知道圖片越小越好,甚至根本不知道如何計算,今天筆者就拋磚引玉一把!   Android中一張圖片(Bitmap)

陣列到底佔用記憶體筆記

一個bool型別佔用1個位元組。int 型別佔用4個位元組。定義的陣列的大小等於陣列大小size*每個元素的大小。 測試方法: 用sizeof的方法可以測試出結果。陣列也可以用這個來測試。 例如

Java中的String到底佔用記憶體空間?你所瞭解的可能都是錯誤的!!

## 寫在前面 > 最近小夥伴加群時,我總是問一個問題:Java中的String類佔用多大的記憶體空間?很多小夥伴的回答著實讓我哭笑不得,有說不佔空間的,有說1個位元組的,有說2個位元組的,有說3個位元組的,有說不知道的,更讓人哭笑不得的是竟然還有人說是2的31次方。那如果真是這樣的話,伺服器的記憶體

java梳理-一個漢字占空間

創建 tex otto new lov lis develop eas XML 面試題:一個漢字占多大空間。事實上這個問題我了解不深的,知道結論不知道為什麽。借此梳理下認識。先回想下java基本類型一基本類型 :簡稱四類八種,聲明變量的同一時候分配了空間。舉比例如以下:

mysql有記憶體?能存多少資料?

Mysql: MySQL 3.22 限制的表大小為4GB。 MyISAM 儲存引擎: 最大表尺寸增加到了65536TB(2567 – 1位元組)。由於允許的表尺寸更大,MySQL資料庫的最大有效表尺寸通常是由作業系統對檔案大小的限制決定的,而不是由MySQL內部限制決定的。 InnoDB 儲存引擎

一張圖片佔記憶體的計算-android

DisplayMetrics 的兩個變數,摘錄官方文件的解釋:     density:The logical density of the display. This is a scaling factor for the Density Independent Pixe

java NEW一個物件之後加入括號

                有兩種情況: 1.初始化物件: Class1 model =&n

filebeat實踐-記憶體佔用-最記憶體佔用

https://yq.aliyun.com/articles/241161 filebeat作為日誌採集agent, 是需要部署到生產伺服器上的.不理解filebeat的工作機制,不瞭解filebeat在實際生產使用中的記憶體使用將會給你帶來意想不到的麻煩. 有些文章

Android 開發繞不過的坑:你的 Bitmap 究竟佔記憶體

0、寫在前面 本文涉及到螢幕密度的討論,這裡先要搞清楚 DisplayMetrics 的兩個變數,摘錄官方文件的解釋: density:The logical density of the display. This is a scalin

L1-040. 最佳情侶身高差【附C++如何保留幾位小數,可設定為對一個物件物件生效】

專家通過多組情侶研究資料發現,最佳的情侶身高差遵循著一個公式:(女方的身高)×1.09=(男方的身高)。如果符合,你倆的身高差不管是牽手、擁抱、接吻,都是最和諧的差度。下面就請你寫個程式,為任意一位使用者計算他/她的情侶的最佳身高。輸入格式:輸入第一行給出正整數N(<=

Bitmap 究竟佔記憶體

reased (probably to 1.5). densityDpi:The screen density expressed as dots-per-inch. 簡單來說,可以理解為 density 的數值是 1dp=density px;densityDp

一個OC物件佔用多少記憶體?

檢視一個NSObject物件佔用多少記憶體 1、引入標頭檔案: #import <objc/runtime.h> #import <malloc/malloc.h> 2、程式碼如下: NSObject* obj = [[NSObject alloc]i

PHPExcel解決記憶體佔用問題-設定單元格物件快取

PHPExcel解決記憶體佔用過大問題-設定單元格物件快取 PHPExcel是一個很強大的處理Excel的PHP開源類,但是很大的一個問題就是它佔用記憶體太大,從1.7.3開始,它支援設定cell的快取方式,但是推薦使用目前穩定的版本1.7.6,因為之前的版本都會不同程度的存在bug,以下是其官方文件

Linux系統used記憶體佔用,而實際系統中個程序並沒有佔用這麼記憶體

問題 新裝伺服器,used記憶體佔用很大,而實際系統中個程序並沒有佔用這麼多記憶體 現象 top檢視下,used很大,如果有其他外部程式向監控伺服器的記憶體,used實際是個比較關鍵的指標,而該指標卻並沒有反應出伺服器實際佔用情況: 原因 實

storm trident 一個batch

conf increase trident eas example part broker 有一個 storm You can increase the batch size by changing "tridentKafkaConfig.fetchSizeBytes" p