虛擬機(jī)研究系列-Java各種類型對(duì)象占用內(nèi)存情況分析(上)

內(nèi)容簡(jiǎn)介

本文深入分析并驗(yàn)證了不同Java對(duì)象占用內(nèi)存空間大小的情況。對(duì)于不同的jvm實(shí)現(xiàn),Java對(duì)象占用的內(nèi)存空間大小可能不盡相同,本文主要分析HotSpot jvm中的情況,實(shí)驗(yàn)環(huán)境為64位window10系統(tǒng)、JDK1.8

對(duì)象頭

在64位機(jī)器上,默認(rèn)不開啟指針壓縮(-XX:-UseCompressedOops)的情況下,對(duì)象頭占用16bytes,開啟指針壓縮(-XX:+UseCompressedOops)則占用12bytes

實(shí)例數(shù)據(jù)

原生類型(primitive type)的內(nèi)存占用如下:

image

對(duì)象引用(reference)類型在64位機(jī)器上,關(guān)閉指針壓縮時(shí)占用8bytes, 開啟時(shí)占用4bytes。

對(duì)齊填充

Java對(duì)象占用空間是8字節(jié)對(duì)齊的,即所有Java對(duì)象占用bytes數(shù)必須是8的倍數(shù)。包含兩個(gè)屬性的對(duì)象:int和byte,并不是占用17bytes(12+4+1),而是占用24bytes(對(duì)17bytes進(jìn)行8字節(jié)對(duì)齊)

對(duì)象內(nèi)存占用(前提回顧)

首先根據(jù)以上的計(jì)算規(guī)則,進(jìn)行一個(gè)簡(jiǎn)單的驗(yàn)證。使用下面的程序進(jìn)行驗(yàn)證:

public class Test {
    public static void main(String[] args) throws InterruptedException {
        TestObject testObject = new TestObject();
        Thread.sleep(600 * 1000);
        System.out.println(testObject);
    }
}

class TestObject {
    private int i;
    private double d;
    private char[] c;
    public TestObject() {
        this.i = 1;
        this.d = 1.0;
        this.c = new char[]{'a', 'b', 'c'};
    }
}

TestObject對(duì)象有四個(gè)屬性,分別為int, double, Byte, char[]類型。在打開指針壓縮(-XX:+UseCompressedOops)的情況下,在64位機(jī)器上,TestObject占用的內(nèi)存大小應(yīng)為:

12(Header) + 4byte(int) + 8byte(double) + 4byte(reference) = 28 (bytes),加上4byte對(duì)齊(padding),最終的大小應(yīng)為32bytes。

image

當(dāng)指針壓縮關(guān)閉時(shí)(-XX:-UseCompressedOops),在64位機(jī)器上,TestObject占用的內(nèi)存大小應(yīng)為:

16(Header) + 4(int) + 8(double) + 8(reference) = 36 (bytes),4字節(jié)對(duì)齊后為 40 bytes。

image

包裝類型

包裝類(Boolean/Byte/Short/Character/Integer/Long/Double/Float)占用內(nèi)存的大小等于對(duì)象頭大小加上底層基礎(chǔ)數(shù)據(jù)類型的大小。

包裝類型的對(duì)象內(nèi)存占用情況如下:

image

數(shù)組

64位機(jī)器上,數(shù)組對(duì)象的對(duì)象頭占用24 bytes,啟用壓縮后占用16字節(jié)。比普通對(duì)象占用內(nèi)存多是因?yàn)樾枰~外的空間存儲(chǔ)數(shù)組的長(zhǎng)度。

  • 基礎(chǔ)數(shù)據(jù)類型數(shù)組占用的空間包括數(shù)組對(duì)象頭以及基礎(chǔ)數(shù)據(jù)類型數(shù)據(jù)占用的內(nèi)存空間。

  • 對(duì)象數(shù)組中存放的是對(duì)象的引用,所以對(duì)象數(shù)組本身的大小=數(shù)組對(duì)象頭+length * 引用指針大小,總大小為對(duì)象數(shù)組本身大小+存放的數(shù)據(jù)的大小之和

舉兩個(gè)例子:

int[10]:

開啟壓縮:16(12Byte(8[標(biāo)記字段]+4[類型指針])+4[數(shù)組長(zhǎng)度大小]) + 10(大小) * 4(32bit的整數(shù)類型) = 56 bytes;

image

關(guān)閉壓縮:24(16Byte(8[標(biāo)記字段]+8[類型指針])+4[數(shù)組長(zhǎng)度大小]+4[padding]) + 10 * 4(32bit的整數(shù)類型) = 64bytes

image

new Integer[3]:

關(guān)閉壓縮:

Integer數(shù)組本身:24(header) + 3 * 8(Integer reference) = 48 bytes;

總共:48 + 3 * 24(Integer) = 120 bytes。

image
開啟壓縮:

Integer數(shù)組本身:16(header) + 3 * 4(Integer reference) = 28+4(padding) -> 32 (bytes)

總共:32 + 3 * 16(Integer)[12byte的對(duì)象頭+4byte的引用reference] = 80 (bytes)

image

String

在JDK1.7及以上版本中,String包含2個(gè)屬性,一個(gè)用于存放字符串?dāng)?shù)據(jù)的char[], 一個(gè)int類型的hashcode, 部分源代碼如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
    /** Cache the hash code for the string */
    private int hash; // Default to 0
}

因此,在關(guān)閉指針壓縮時(shí),一個(gè)String本身需要 16(Header) + 8(char[] reference) + 4(int) = 32 bytes。

除此之外,一個(gè)char[]占用24byte(其中有4byte的對(duì)齊padding) + length * 2 bytes(8字節(jié)對(duì)齊), 即一個(gè)String占用的內(nèi)存空間大小為:

56 + length * 2 bytes(char的18bit) (8字節(jié)對(duì)齊)。

舉幾個(gè)例子。

一個(gè)空字符串("")的大小應(yīng)為:56 + 0 * 2 bytes = 56 bytes

image

字符串"abc"的大小應(yīng)為:56 + 3 * 2 = 62(8字節(jié)對(duì)齊)->64 (bytes)

image

字符串"abcde"的大小應(yīng)為:56 + 5 * 2 = 66->72 (bytes)

image

字符串"abcde"在開啟指針壓縮時(shí)的大小為

String本身:12(Header) + 4(char[] reference) + 4(int hash) = 20(padding) -> 24 (bytes);

存儲(chǔ)數(shù)據(jù):16(char[] header) + 5 * 2 = 26(padding) -> 32 (bytes)

總共:24 + 32 = 56 (bytes)

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容