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

2020-12-11 moon聊技術

小小面試一下

前言蜜語

最近馬師傅火的不要不要的,雖然沒有搶到耗子尾汁的商標註冊權,但是必須得蹭一波馬師傅的熱度,下面就是閃電五連鞭的教學環節,你準備好了嗎!

在正式內容開始前先甩兩篇關於類加載機制和內存布局的文章,因為今天的內容多少與這兩篇文章有直接的聯繫,對這方面還比較薄弱的朋友可以先看看,地址我放在下面。

jvm┃java內存區域,跳槽大廠必會知識點!

moon不講武德!!!一個類加載機制給面試官說蒙了!!

今天本文的內容就針對剛剛模擬面試兩個問題

1.對象的創建過程

2.對象的內存布局

對象的創建過程

以下內容基於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佔用4位元組,classpoint佔用8位元組,Interface data無數據,總共是12位元組,由於對象需要為8的整數倍,Padding會補充4個字節,總共佔用16位元組的存儲空間。在沒有指針的情況下,markword佔用8位元組,classpoint佔用8位元組,Interface data無數據,總共是16位元組。結語

今天的文章和大家介紹了一個對象的創建過程,從它的出生到死亡,都經歷了什麼?也和大家詳細的說明了對象的內存布局,深入解剖了一下對象的身體構造,這下面試官再問你,可就有的聊了,這篇文章的內容還是比較肝的,需要大家認真閱讀一下,當然,也可以私下聯繫我,我是moon,下期見~

相關焦點

  • 面試官:Object o=new Object()佔用了多少字節?
    面試的時候,要是面試官問了標題那種問題,你知道怎麼解答嗎? 本文內容將針對以上面試問題做出解答。 對象的內存布局 回到文章標題,Object o = new Object();到底佔用多少個字節?這道題的目的其實就是考驗看你對對象的內存布局了解的是否清晰。先上圖:
  • 面試官問:能否模擬實現JS的new操作符(高頻考點)
    前言這是面試官問系列的第一篇,旨在幫助讀者提升JS基礎知識,包含new、call、apply、this、繼承相關知識。面試官問系列文章如下:感興趣的讀者可以點擊閱讀。1.面試官問:能否模擬實現JS的new操作符2.面試官問:能否模擬實現JS的bind方法3.面試官問:能否模擬實現JS的call和apply方法4.面試官問:JS的this指向5.面試官問:JS的繼承用過Vuejs的同學都知道,需要用new操作符來實例化。
  • 美團面試官問我一個字符的String.length()是多少,我說是1,面試官說你回去好好學一下吧
    喬哥:前幾天我寫的一篇文章:面試官問你編碼相關的面試題,把這篇甩給他就完事![1]裡面對於Java的字符使用的編碼有介紹:Java中 有內碼和外碼這一區分簡單來說•內碼:char或String在內存裡使用的編碼方式。•外碼:除了內碼都可以認為是「外碼」。(包括class文件的編碼)而java內碼:unicode(utf-16)中使用的是utf-16.
  • 聊聊 CSS3 中的 object-fit 和 object-position
    這個當然不是我頭腦風暴來的,而是引用別人的解釋:引用(http://openwares.net/internet/css_replaced_element.html)常見的替換元素有<video>、<object>、<img>、<input type=」image」>、<svg>、<svg:image>
  • 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無法轉成對象,所以如果它們作為參數,就會報錯。
  • Spring雜談 | 什麼是ObjectFactory?什麼是ObjectProvider?
    > objectFactory);這個方法的目的就是從對於的域中獲取到指定名稱的對象。為什麼要傳入一個objectFactory呢?主要是為了方便我們擴展自定義的域,而不是僅僅使用request,session等域。void registerResolvableDependency(Class<?
  • 變量類型測試函數的使用:六、is_object的用法
    因為在PHP中最常用到的數據類型就是數組和對象,所以我們今天就來講講is_object的用法;(等之後了再來詳細講解詳細的內容)is_objectis_object — 檢測變量是否是一個對象is_object 描述
  • 面試官:老是問我深淺拷貝問題,自己看文章
    面試官:老是問我深淺拷貝問題,自己看文章你如果出去面試,面試官老是會問你一些很神奇,但又不得不去了解的問題,今天這個問題就是其中之一,在工作中,其實我們經常使用對象拷貝,數組拷貝,但是往往會忽略了其中的原理,今天我們就來一探究竟。
  • Python 字節碼
    百度上目前還搜不到 Python 字節碼全套內容,於是搭了梯子爬了下官方的教程。我們都知道 python 是解釋性語言,但 python 還有個編譯過程,這個過程是將 python 代碼編譯成 字節碼,類似於彙編語言的一條一條指令。執行時,首先會讀取指令,底層的 C 語言代碼中寫有上千行的 switch case 語句與這個指令相匹配並執行相關代碼。
  • Python 之type 與object
    1、Python type 與objectpython 當中的type 是所有內置對象或者類的基類型,object 是所有類繼承的基類 因此int、str、list、tuple 等等這些內置的類這些都是type類的實例對象。因為type 也是類,因此type的基類也是object。
  • 面試官問:能否模擬實現JS的call和apply方法
    前言這是面試官問系列的第三篇,旨在幫助讀者提升JS基礎知識,包含new、call、apply、this、繼承相關知識。面試官問系列文章如下:感興趣的讀者可以點擊閱讀。1.面試官問:能否模擬實現JS的new操作符2.面試官問:能否模擬實現JS的bind方法3.面試官問:能否模擬實現JS的call和apply方法4.面試官問:JS的this指向5.面試官問:JS的繼承之前寫過兩篇《面試官問:能否模擬實現JS的new操作符》和《面試官問:能否模擬實現JS的bind
  • 詭異 | Spark使用get_json_object函數
    一、問題現象:使用spark sql調用get_json_object函數後,報如下錯誤:yarn 容器被
  • 你所使用的Python對象佔用了多少內存?(附代碼)
    眾所周知,Python對象圖(列表、元組和基元類型的嵌套字典)佔用了大量內存。這可能是一個更為嚴格的限制因素,因為這對緩存、虛擬內存、與其他程序的多租戶產生了影響,而且通常會更快地耗盡一種稀缺且昂貴的資源——可用內存。事實證明,想要弄清楚實際消耗了多少內存並非易事。在本文中,我將向你介紹Python對象內存管理的複雜性,並展示如何準確地去測量所消耗的內存。
  • 面試官問:能否模擬實現JS的bind方法(高頻考點)
    可以點擊上方的話題JS基礎系列,查看往期文章寫於2018年11月21日,發布在掘金閱讀量1.3w+前言這是面試官問系列的第二篇,旨在幫助讀者提升JS基礎知識,包含new、call、apply、this、繼承相關知識。面試官問系列文章如下:感興趣的讀者可以點擊閱讀。
  • 有關 HashMap 面試會問的一切
    HashMap 用起來很簡單,底層實現也不複雜,先來看幾道常見的面試題吧。相信大家多多少少都能回答上來一點,不清楚的地方就仔細閱讀本文啦~這篇文章帶你深挖到 HashMap 的老祖宗,保證吊打面試官為什麼重寫 equals() 就必須要重寫 hashCode()?
  • 深入理解Django時區及naive datetime object和aware datetime object的區別
    什麼是naive datetime object?什麼又是aware datetime object? 在Django配置中如果將settings.TIME_ZONE設置為中國時區(Asia/Shanghai),為什麼以下時間函數(now)會得到時間相差較大的結果?
  • 年末的大廠前端面試總結(20屆雙非二本)-終入字節
    大多數情況下,換一份滿意的工作,整個面試流程加offer審核到offer call再到最終郵件offer,耗時一個月是很正常的。在職面試都會有焦慮感,更何況是裸辭。如果工作年限很短,又是裸辭,那我只能說在簡歷篩選上會很吃虧。比如我,投字節15個崗位,都被幹掉,到第16個才約上面試。
  • 面試官問我什麼是擴展自適應機制
    Hola,我是 yes。這篇繼續之前提到的 Dubbo SPI 來講講擴展點自適應機制(這篇文末會畫個 Dubbo SPI 完整的流程圖,來幫助大家理解,如果沒看過上一篇的建議先看下Dubbo 靠它嶄露頭角)。