Java計算對象大小的方法詳解
序
在Java應用程序的性能優(yōu)化場景中,時常需要考慮Java對象的大小,以便觀測、評估后,進一步提出優(yōu)化方案:
- 占用內(nèi)存的大小。(比如 本地內(nèi)存)
- 對象數(shù)據(jù)在網(wǎng)絡傳輸中占用的網(wǎng)絡帶寬
- 對象數(shù)據(jù)在存儲時占用的磁盤空間
- ...
概述
對象大小如何計算
對象大小包括倆部分的內(nèi)容,對象頭和對象內(nèi)容:

對象頭
此處假設是64位的JVM
- 對象地址,占4個字節(jié)。
- 對象標記,占8個字節(jié),包括鎖標記,hashcode, age 等。
- 數(shù)組長度標記,占4個字節(jié)。如果對象是一個數(shù)組,會有此標記,否則沒有。
對象內(nèi)容
對象內(nèi)部屬性。如果屬性是對象的話,那么記錄的是對象的地址,占用4個字節(jié)。
8字節(jié)對齊
Java對象采用的是8字節(jié)對齊。對象大小必須是8的倍數(shù),不足需要補齊。
比如,計算一個對象只需要20字節(jié),那么實際占用24字節(jié)。
計算對象大小的方法
方法1和方法2,在 String 對象的計算上,存在差異;Integer 和 Map 的計算,經(jīng)簡單檢驗:不存在差異。
方法1:基于 JDK 原生庫 【推薦】
jdk 1.8
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ObjectCalculatorTest {
public static void main(String[] args) {
String text = "Hello World!"; //12 chars
Long objectSizeBytes = ObjectSizeCalculator.getObjectSize(text);
log.info("objectSizeBytes: {} bytes", objectSizeBytes );//64 bytes
Integer number = new Integer(11);
objectSizeBytes = ObjectSizeCalculator.getObjectSize(number);
log.info("objectSizeBytes: {} bytes", objectSizeBytes );//16 bytes
Map<String, String> map = new HashMap<>();
objectSizeBytes = ObjectSizeCalculator.getObjectSize(number);
log.info("objectSizeBytes: {} bytes", objectSizeBytes );//48 bytes
}
}
方法2:基于lucene-core庫
引入依賴
<dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>8.7.0</version> </dependency>
計算對象大小
jdk 1.8
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.util.RamUsageEstimator;
@Slf4j
public class ObjectCalculatorTest {
public static void main(String[] args) {
String text = "Hello World!"; //12 char = 12 byte
objectSizeBytes = RamUsageEstimator.shallowSizeOf( text );
log.info("objectSizeBytes: {} bytes", objectSizeBytes );//24 bytes
Integer number = new Integer(11);
System.out.println(RamUsageEstimator.shallowSizeOf(number));//16 bytes
Map<String, String> map = new HashMap<>();
System.out.println(RamUsageEstimator.shallowSizeOf(map));//48 bytes
}
}
案例分析(基于lucene-core庫)
Integer 對象大小分析
- 它是對象,占用4個字節(jié)
- 對象標記,占用8個字節(jié)
- 查看源碼,發(fā)現(xiàn):
Integr 內(nèi)容只有以下一個非static的屬性,是一個int的基本類型屬性,占用4個字節(jié).
static 修飾的方法屬性都是存儲在方法區(qū)的,不占用對象空間。
/**
* The value of the {@code Integer}.
*
* @serial
*/
private final int value;
故 total = 4 + 8 + 4 = 16
HashMap 對象大小分析
- 它是對象,占用4個字節(jié)
- 對象標記,占用8個字節(jié)
- 查看源碼,發(fā)現(xiàn):
HashMap 是繼承了 AbstractMap 的,AbstractMap 中有以下的倆個屬性,一共占用8個字節(jié)。因為只是存儲了keySet, values 的地址
transient Set<K> keySet; transient Collection<V> values;
HashMap 中有以下屬性,共占用 6 * 4 = 24 個字節(jié)。
transient Node<K,V>[] table; transient Set<Map.Entry<K,V>> entrySet; transient int size; transient int modCount; int threshold; final float loadFactor;
total = 4 + 8 + 8 + 24 = 44, 由于 java 是8字節(jié)對齊的,故一共是 48 字節(jié)。
到此這篇關于Java計算對象大小的方法詳解的文章就介紹到這了,更多相關Java計算對象大小內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot深入理解之內(nèi)置web容器及配置的總結
今天小編就為大家分享一篇關于SpringBoot深入理解之內(nèi)置web容器及配置的總結,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
maven profile實現(xiàn)多環(huán)境配置的示例
這篇文章主要介紹了maven profile實現(xiàn)多環(huán)境配置的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01
SpringBoot2底層注解@ConfigurationProperties配置綁定
這篇文章主要介紹了SpringBoot2底層注解@ConfigurationProperties配置綁定,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)登錄接口整合阿里云短信詳情
這篇文章主要為大家介紹了實戰(zhàn)分布式醫(yī)療掛號系統(tǒng)登錄接口整合阿里云短信詳情,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>2022-04-04

