菜雞每日一面系列打卡25天
每天一道面試題目
助力小夥伴輕鬆拿offer
堅持就是勝利,我們一起努力!
題目描述
從JVM層面談談你對“對象”的理解。
題目分析
在開始之前,菜雞想先引用一句非常經典的話,“Java與C++之間有一堵由內存動態分配和垃圾收集技術所圍成的高牆,牆外面的人想進去,牆裏面的人卻想出來。”這簡直是程序員版的現實圍城。而這段話裏提到的內存動態分配和垃圾收集技術,都與“對象”這個詞脫不了干係。
衆所周知(對了解Java的人而言),Java是一門面向對象的語言。“對象”這個概念已經深入了每個面嚮對象語言程序員的內心,這包括但不限於Java、C++、Python……而本文將要探究的就是JVM層面對象的概念。理解了這一概念,會對面向對象有更加深刻的認識。
題目解答
01
對象的創建
在Java的世界裏永遠不缺“對象”,如果缺,new一個。就是這個神奇的new關鍵字,分分鐘解決了現實世界中找“對象”的難題。究竟是怎麼做到的呢?這種神祕的力量值得我們仔細研究一波。注意,下文所提到的對象僅限於普通Java對象,不包括數組和Class對象等。
首先,需要了解Java程序運行的大致過程,我們編寫的源程序(.java文件)經過編譯器編譯之後得到(.class文件),這也是Java跨平臺的關鍵,然後JVM將字節碼文件解釋成機器碼運行。
接下來,我們用一張圖來描述當JVM遇到一條字節碼的new指令時的反應。
注意,這張圖僅僅描述的是JVM層面創建對象的流程,至此,其實並沒有得到你想要的對象,後續會執行Class文件中的<init>()方法進行對象初始化。
02
對象的內存佈局
第一部分的圖中中提到了對象頭這個概念。在HotSpot虛擬機裏,對象在堆內存中的存儲佈局可以劃分爲三個部分:對象頭、實例數據和對齊填充。
對象頭的內容可分爲兩部分:Mark Word和類型指針。
Mark Word的內容如下表所示:
類型指針(非必須)則是對象指向它的類型元數據的指針,JVM通過這個指針來確定該對象是哪個類的實例。
實例數據存儲的是對象的有效信息,即我們在程序中定義的類的屬性(包括從父類繼承的)。
對齊填充起到佔位符的作用。HotSpot虛擬機的自動內存管理系統要求對象起始地址必須是8字節的整數倍,也即任何對象的大小都必須是8字節的整數倍。對象頭部分已經被設計成天然滿足8字節的整數倍了,而對象的實例數據部分如果不滿足,就需要進行對齊填充。
03
對象的訪問定位
常見的對象訪問定位方式主要有兩種:句柄訪問,直接指針訪問。
句柄訪問:
過程
① reference → 句柄池(包括實例數據指針與類型數據指針)
②實例數據指針 → 對象實例數據、類型數據指針 → 對象類型數據
優勢
reference中存儲的是穩定句柄地址,在對象被移動時只會改變句柄中的實例數據指針,而不改變reference。
直接指針訪問:
過程
①reference → 對象實例數據
②對象實例數據 → 對象類型數據
優勢
速度更快,節省了一次指針定位的時間開銷。
參考資料
《深入理解Java虛擬機》第3版 周志明
相關鏈接
以上便是菜雞對JVM層面對象的一些總結,供大家參考。
學習 | 工作 | 分享
????長按關注“有理想的菜雞”
只有你想不到,沒有你學不到