面試官:Object o=new Object()佔用了多少字節?

2021-01-07 騰訊網

作者 | 哪兒來的moon 責編 | 張文

頭圖 | CSDN 下載自視覺中國

來源 | 哪兒來的moon(ID:onetraveller_llxz)

面試的時候,要是面試官問了標題那種問題,你知道怎麼解答嗎?

本文內容將針對以上面試問題做出解答。

對象的創建過程

以下內容基於 HotSpot VM 分代模型。

這張圖其實就能完整的說明一個對象的創建過程到底發生了什麼。從左上角開始,一步一步來:

一個對象 new 出來先判斷線程棧是否能分配下;

如果能分配下,直接分配在棧中。

如果分配不下則進行第二步。

判斷該對象是否足夠大;

如果足夠大,則直接進入老年代。

如果不夠大,則進行第三步。

判斷創建對象的線程的 TLAB(本地線程緩衝區)空間是否足夠;

如果足夠,直接分配在 TLAB 中。

如果不夠,則進入 Eden 區中其他空間。然後進行第四步。

GC 清除;

如果清除掉了該對象,則直接結束。

如果沒有清除掉對象,進行第5步。

此刻對象進入 Survivor 1 區,判斷年齡是否足夠大;

如果年齡足夠大,則直接進入 old 區域。

如果年齡不夠大,則進入 Survivor 2 區,然後進入第4步,循環往復。

通過這張流程圖的步驟解析之後,大家應該對一個對象的創建過程有一個相對清晰的思路了。但其實會有很多小細節容易被忽略,這也就是為什麼 jvm 會在對象的創建過程中不遺餘力的解釋,細分多種情況。

為了讓大家更深入地理解,我們再來看看下面幾個問題:

為什麼對象會選擇先分配在棧中?

首先,棧是線程私有的,將對象優先分配在棧中,可以通過 pop 直接將對象的所有信息、空間直接清除,當線程消亡的時候也可以直接清理這一塊的 TLAB 區域。

為什麼 jvm 會讓大對象會直接進入老年代?

大對象需要連續的空間來存儲,如果不存入老年代,對 jvm 來說就是一個負擔;倘若沒有足夠的空間就有可能導致提前觸發 gc 來清理空間來安置大對象。

為什麼會選擇先進入 TLAB?

TLAB 是線程本地緩衝區,TLAB 的好處就是防止不同線程創建對象選擇同一塊兒內存區域而產生競爭,大大降低其競爭概率。

為什麼會有兩個 Survivor 區?並且存活且年齡不夠大的對象會從一個Survivor 區轉到另一個 Survivor 區?

根據根可達算法,jvm 會尋找到所有正在使用的對象,沒有使用的就是垃圾。通常來說,大部分對象都是用完就拋棄的,所以真正在 Survivor 區長時間存活的對象非常少,將這部分對象從一個 Survivor 區轉到另一個 Survivor 區後,就可以直接對這個 Survivor 區進行全量的空間回收,效率會很高。

對象的內存布局

回到文章標題,Object o = new Object();到底佔用多少個字節?這道題的目的其實就是考驗看你對對象的內存布局了解的是否清晰。先上圖:

在 java 中對象的內存布局分為兩種情況:非數組對象和數組對象,數組對象和非數組對象的區別就是需要額外的空間存儲數組的長度length

對象頭

對象頭又分為 MarkWord 和 Class Pointer 兩部分。

MarkWord:包含一系列的標記位,比如輕量級鎖的標記位、偏向鎖標記位、gc記錄信息等等。在32位系統佔4位元組,在64位系統中佔8位元組。

ClassPointer:用來指向對象對應的Class對象(其對應的元數據對象)的內存地址。在32位系統佔4位元組,在64位系統中佔8位元組。

Length:只在數組對象中存在,用來記錄數組的長度,佔用4位元組。

Interface data

Interface data:對象實際數據。對象實際數據包括了對象的所有成員變量,其大小由各個成員變量的大小決定。(這裡不包括靜態成員變量,因為它是在方法區維護的)

Padding

Padding:Java 對象佔用空間是 8 字節對齊的,即所有 Java 對象佔用 bytes 數必須是 8 的倍數。這是因為當我們從磁碟中取一個數據時,不會說我想取一個字節就是一個字節,都是按照一塊兒一塊兒來取的。這一塊大小是 8 個字節,所以為了完整,padding 的作用就是補充字節,保證對象是 8 字節的整數倍。

小貼士:moon 在上文特意標註了 32 位系統和 64 位系統不同區域佔用空間大小的區別,是因為對象指針在 64 位 JVM 下的尋址更長,所以相比 32 位會多出來更多佔用空間。

現在假設一個場景,公司現在項目部署的機器是 32 位的, 老闆要讓你將項目遷移到 64 位的系統上,但是 64 位系統比 32 位系統需要更多佔用空間,應該怎麼辦?

正常來說我們是不需要這一部分多餘空間的,因為 jvm 已經幫你考慮好了,那就是指針壓縮。

指針壓縮

-XX:+UseCompressedOops 這個參數就是 JVM 提供的解決方案。通過壓縮指針,佔用的空間就會被壓縮為原來的一半,節約空間。classpointer 參數大小就受到其影響。

那麼Object o = new Object()到底佔用多少個字節?

通過剛才內存布局的學習後,這個問題就很好回答了。面試官其實就是想問你對象的內存布局的理解是怎樣的。

我們這裡就針對這個問題的結果分析下,這裡分兩種情況:

在開啟指針壓縮的情況下,markword 佔用 8 字節,classpoint 佔用 4 字節,Interface data 無數據,總共是12位元組,由於對象需要為8的整數倍,Padding 會補充4個字節,總共佔用16位元組的存儲空間。

在沒有指針壓縮的情況下,markword 佔用 8 字節,classpoint 佔用 8位元組,Interface data 無數據,總共是16位元組。

了解了對象的創建過程和對象的內存布局,Object o = new Object() 佔用了多少字節?這類問題就不是難事了!

相關焦點

  • 面試官問我:Object o = new Object() 佔用了多少個字節?
    在正式內容開始前先甩兩篇關於類加載機制和內存布局的文章,因為今天的內容多少與這兩篇文章有直接的聯繫,對這方面還比較薄弱的朋友可以先看看,地址我放在下面。jvm┃java內存區域,跳槽大廠必會知識點!moon不講武德!!!一個類加載機制給面試官說蒙了!!
  • The shiny object? 閃亮之物
    In actuality, the shiny object can be misleading and a total waste of time.The shiny object is also called the bright shiny object.
  • ES6對象新增方法-Object.is與Object.assign
    const arr = [1,2,3]let obj1 = typeof(Object.assign(arr))console.log(obj1)//object由於undefined和null無法轉成對象,所以如果它們作為參數,就會報錯。
  • 聊聊 CSS3 中的 object-fit 和 object-position
    趁著今天有點空閒,決定再來折騰一下CSS3中的兩個屬性:object-fit和object-position。這兩個奇葩的屬性是做什麼的呢?其實它們是為了處理替換元素(replaced elements)的自適應問題,簡單的說,就是處理替換元素的變形(這裡指長寬比例變形)問題。
  • 面試官問:能否模擬實現JS的new操作符(高頻考點)
    前言這是面試官問系列的第一篇,旨在幫助讀者提升JS基礎知識,包含new、call、apply、this、繼承相關知識。面試官問系列文章如下:感興趣的讀者可以點擊閱讀。1.面試官問:能否模擬實現JS的new操作符2.面試官問:能否模擬實現JS的bind方法3.面試官問:能否模擬實現JS的call和apply方法4.面試官問:JS的this指向5.面試官問:JS的繼承用過Vuejs的同學都知道,需要用new操作符來實例化。
  • Python 字節碼
    百度上目前還搜不到 Python 字節碼全套內容,於是搭了梯子爬了下官方的教程。我們都知道 python 是解釋性語言,但 python 還有個編譯過程,這個過程是將 python 代碼編譯成 字節碼,類似於彙編語言的一條一條指令。執行時,首先會讀取指令,底層的 C 語言代碼中寫有上千行的 switch case 語句與這個指令相匹配並執行相關代碼。
  • Spring雜談 | 什麼是ObjectFactory?什麼是ObjectProvider?
    > objectFactory);這個方法的目的就是從對於的域中獲取到指定名稱的對象。為什麼要傳入一個objectFactory呢?主要是為了方便我們擴展自定義的域,而不是僅僅使用request,session等域。void registerResolvableDependency(Class<?
  • Python 之type 與object
    1、Python type 與objectpython 當中的type 是所有內置對象或者類的基類型,object 是所有類繼承的基類 因此int、str、list、tuple 等等這些內置的類這些都是type類的實例對象。因為type 也是類,因此type的基類也是object。
  • 變量類型測試函數的使用:六、is_object的用法
    因為在PHP中最常用到的數據類型就是數組和對象,所以我們今天就來講講is_object的用法;(等之後了再來詳細講解詳細的內容)is_objectis_object — 檢測變量是否是一個對象is_object 描述
  • 詭異 | Spark使用get_json_object函數
    一、問題現象:使用spark sql調用get_json_object函數後,報如下錯誤:yarn 容器被
  • 深入理解Django時區及naive datetime object和aware datetime object的區別
    什麼是naive datetime object?什麼又是aware datetime object? 在Django配置中如果將settings.TIME_ZONE設置為中國時區(Asia/Shanghai),為什麼以下時間函數(now)會得到時間相差較大的結果?
  • An object lesson? 實物教學課
    Reader question:Please explain 「object lesson」, as in 「the first meal was an object lesson of much variety.」
  • Object.assign 原理及其實現
    本篇文章會先介紹淺拷貝 Object.assign 的實現原理,然後帶你手動實現一個淺拷貝,並在文末留下一道面試題,期待你的評論。淺拷貝 Object.assign上篇文章介紹了其定義和使用,主要是將所有可枚舉屬性的值從一個或多個源對象複製到目標對象,同時返回目標對象。
  • 解決Asp程序的Server.CreateObject錯誤
    如果是英文版,錯誤信息如下:程序代碼: Error Type:Server object, ASP 0178 (0x80070005)The call to Server.CreateObject failed while checking permissions. Access is denied to this object.
  • 你所使用的Python對象佔用了多少內存?(附代碼)
    眾所周知,Python對象圖(列表、元組和基元類型的嵌套字典)佔用了大量內存。這可能是一個更為嚴格的限制因素,因為這對緩存、虛擬內存、與其他程序的多租戶產生了影響,而且通常會更快地耗盡一種稀缺且昂貴的資源——可用內存。事實證明,想要弄清楚實際消耗了多少內存並非易事。在本文中,我將向你介紹Python對象內存管理的複雜性,並展示如何準確地去測量所消耗的內存。
  • 背「反對」英語單詞-oppose,object,against
    一、oppose [pz] v.反對; 抵制; (在競賽中)與…對壘,與…角逐1、拆開:o ppose聯想:我 拋屍二、object [bdkt , bdekt] n.
  • 美團面試官問我一個字符的String.length()是多少,我說是1,面試官說你回去好好學一下吧
    * * @return the length of the sequence of characters represented by this * object. */ public int length() { return value.length; }接著使用google翻譯
  • 中考英語近義詞辨析: aim/ purpose/ object
    中考英語近義詞辨析: aim/ purpose/ object   Ⅰ. aim 「目的」指抱有一種明確的目的,並意味著為之實現而竭盡全力。如:   ① What’s your aim in life?你的人生目的是什麼?
  • Thing Stuff Object 都表示東西用途有別
    Thing, stuff, object 都有表示"東西"的意思,通常我們在使用中有啥主要區別呢? 舉例如下:1.Object 物體,東西例: What object is that far away ?遠處是什麼東西?He is looking at an object on land.他正看著陸地上某個物體。