自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

對象很大,你忍一下

開發(fā) 前端
針對這句話我收到了幾位讀者的私信,表示不明白為啥不過一個簡簡單的二維數(shù)組會有這么大的開銷,本來這個問題在我正在寫的類加載機制中有詳述,不過文章還沒寫完(估計本周發(fā)),所以我專門抽出這個問題探討一下,五分鐘就能看懂。

[[442389]]

本文轉載自微信公眾號「碼海」,作者坤哥。轉載本文請聯(lián)系碼海公眾號。

你好,我是坤哥

上一篇Java 進階之字節(jié)碼剖析中我曾經(jīng)提到這么一段話

int[128][2] ,int[256] 這兩個數(shù)組看起來一樣,但實際上前者比后者多了 246% 的額外開銷

針對這句話我收到了幾位讀者的私信,表示不明白為啥不過一個簡簡單的二維數(shù)組會有這么大的開銷,本來這個問題在我正在寫的類加載機制中有詳述,不過文章還沒寫完(估計本周發(fā)),所以我專門抽出這個問題探討一下,五分鐘就能看懂

Java 對象模型

HotSpot JVM 底層使用名為 oops (Ordinary Object Pointers) 的數(shù)據(jù)結構來表示對象的對象頭

  1. class oopDesc { 
  2.   friend class VMStructs; 
  3.   private: 
  4.     volatile markOop  _mark; 
  5.     union _metadata { 
  6.       Klass*      _klass; 
  7.       narrowKlass _compressed_klass; 
  8.     } _metadata; 
  9.     ... 

JVM 每創(chuàng)建一個對象,相當于創(chuàng)建了一個 oopDesc 的對象,即 instanceOopDesc 來表示這個對象,保存在堆中,如下圖所示

可以看到 Java 對應主要由以下三部分組成

  • 對象頭(Header)
  • 對象實例數(shù)據(jù)(instance data)
  • 對齊填充(Padding)

其中對象頭又包含三個部分

  • markWord: 即 _mark:markOop,用于存儲對象運行時的數(shù)據(jù),好比 HashCode、鎖狀態(tài)標志、GC分代年齡等。這部分在 64 位操作系統(tǒng)下占 8 字節(jié),32 位操作系統(tǒng)下占 4 字節(jié)
  • 指針:指向方法區(qū)中的類元數(shù)據(jù)(類信息)的指針,這部分就涉及到指針壓縮的概念,在開啟指針壓縮的狀況下占 4 字節(jié),未開啟狀況下占 8 字節(jié),默認是開啟的

數(shù)組長度:這部分只有是數(shù)組對象才有,若是非數(shù)組對象就沒這部分。這部分占 4 字節(jié)。

除此之外對象還有兩個部分值得我們注意

對象實例數(shù)據(jù)(instanceData): 用于存儲對象中的各種類型的字段信息(包括從父類繼承來的)

對齊填充:Java 對象大小默認按 8 字節(jié)對齊的,如果「對象頭」+「對象實際數(shù)據(jù)」不足8的位數(shù),對齊填充會補齊相應的字節(jié)以讓對象大小達到 8 的倍數(shù)

Java 數(shù)組大小

知道了對象模型的表示,再來看數(shù)組的大小,首先必須明確兩點

在 Java 中數(shù)組是一種特殊的對象(也是對象,也有對象頭)

一個多維數(shù)組是一個簡單數(shù)組的數(shù)組, 例如,一個二維數(shù)組的每一行都是一個獨立的數(shù)組對象

接下來我們來看看一維數(shù)組 int[256] 在內存中有多大,一維數(shù)組其實可以認為是普通的對象,首先對象頭可以知道是 8(markword) + 4(kclass) + 4(數(shù)組長度)= 16 字節(jié),對象實際數(shù)據(jù)大小為 256 * 4(int 大小為 4 個字節(jié)) = 1024 字節(jié),所以此時總的字節(jié)數(shù)為 16 + 1024 = 1040 字節(jié),是 8 的位數(shù)(1040/8 = 130),所以 padding 為 0, 也就是說 int[256] 一維數(shù)組的字節(jié)大小為 1040 字節(jié)

再來看一下二維數(shù)組 int[128][2] 的大小,我們知道在 C 語言中二維數(shù)組(事實上是任何多維數(shù)組)本質上是一維數(shù)組通過指針操作來實現(xiàn)的,但在 Java 中多維數(shù)組是由一系列的嵌套數(shù)組組成,也就是說對于二維數(shù)組而言,每一行(int[0][…],int[1][…],…,int[127][…])都對應一個數(shù)組對象,都需要額外的開銷,一圖勝千言,如下所示

先來看左邊的對象大?。?/p>

數(shù)組的每一行 int[0],int[1],..int[127] 其實都是指向數(shù)組的指針,為 4 個字節(jié),所以左邊對象占用空間大小為 16 + 4 * 128 = 528,是 8 的倍數(shù)(528/8 = 66),所以 padding 為 0,所以總大小為 528

再來看左邊的 int[0] 等指向的數(shù)組對象大小:

由于左邊每個行數(shù)組的指向都指向了兩個元素的數(shù)組(int[x][0],int[x][1]),它們的對象大小為 16 + 4 + 4 = 24,是 8 的倍數(shù),所以 padding 為 0 ,而總共有 128 個這樣的對象,所以右邊總的對象大小為 128 * 24 = 3072

由于可知 int[128][2] 對象大小為 528 + 3072 = 3600 字節(jié),比一維數(shù)組 int[256](1024 字節(jié))多了 246% !

上述計算的是否正確呢,我們可以用 JDK 自帶的 ObjectSizeCalculator 來計算一下,如下:

與我們的計算結果完全一致!

 

其實不光是二維數(shù)組,包括字節(jié)串,普通的對象開銷也一般會比對象實際數(shù)據(jù)大幾倍,到此我相信你不難明白上一篇中開頭這樣一段話的含義了:kafka 中為啥要使用 pageCache 了, 因為如果不用頁緩存,而是用 JVM 進程中的緩存,對象的內存開銷會非常大(通常是真實數(shù)據(jù)大小的幾倍甚至更多)

 

責任編輯:武曉燕 來源: 碼海
相關推薦

2022-09-19 08:48:03

項目初始化線程

2021-05-31 06:28:35

AutoMapper對象映射器

2018-01-26 09:01:16

對象存儲Java

2022-09-23 15:01:33

圖片加載代碼

2023-05-09 08:25:26

Gaussdb數(shù)據(jù)庫開源數(shù)據(jù)庫

2024-03-01 18:55:54

內存調試Go 語言

2023-08-18 20:50:22

2010-02-25 13:03:13

迅雷

2023-11-23 17:02:34

LinuxSED工具

2021-05-22 11:55:29

Python 開發(fā)編程語言

2018-12-06 13:52:07

2024-01-10 08:08:25

Python空值校驗開發(fā)

2018-04-09 15:36:01

數(shù)據(jù)庫Oracle數(shù)據(jù)復制

2017-09-22 14:12:33

Android字體 Typeface

2022-12-03 18:24:13

數(shù)據(jù)能力場景

2022-08-25 14:42:45

JavaScrip字符串

2020-06-08 08:20:11

Redis高可用集群

2012-01-11 10:17:08

服務器關鍵業(yè)務計劃停機

2021-04-21 14:19:52

javaignalHandle接口

2020-08-27 08:31:11

DDD可視化模型
點贊
收藏

51CTO技術棧公眾號