調(diào)用一個實(shí)例方法jvm竟然都為我們做了這些!

1.前言

這是最近面試騰訊日常實(shí)習(xí)的一個面試題拾因,自己答得不是很好婴氮,故重新分析下。

題目:java的內(nèi)存模型有了解過嗎盾致?說說new 一個對象,并調(diào)用方法返回一個值荣暮,這之中jvm做了什么庭惜,棧楨變化是怎么樣的?

知識點(diǎn)主要是jvm的內(nèi)存模型穗酥、對象加載過程护赊、虛擬機(jī)執(zhí)行引擎,自己雖然也啃過《JVM高級特性與最佳實(shí)踐》這本書砾跃,內(nèi)存模型和對象加載過程答得還行骏啰,棧楨變化的細(xì)節(jié)沒答好,故本篇側(cè)重于棧楨變化的分析抽高,其他兩個問題直接給出答案判耕。

1.1 java內(nèi)存模型

java內(nèi)存模型分為線程公有和線程私有,線程公有包括gc堆和方法區(qū)翘骂,線程私有包括操作計(jì)數(shù)器壁熄、虛擬機(jī)棧、本地方法棧碳竟,如下圖草丧。


個人學(xué)習(xí)的筆記圖

1.2 new一個對象,jvm都做了什么

對象加載過程

其中莹桅,類加載包括加載昌执、驗(yàn)證、準(zhǔn)備诈泼、解析懂拾、初始化,不是本篇的重點(diǎn)铐达,這里不再展開委粉,有興趣的同學(xué)可以看看《JVM高級特性與最佳實(shí)踐》第九章。

2.分析

接下來主要分析new一個對象并調(diào)用方法娶桦,棧楨變化贾节。
簡單分析代碼如下汁汗,聲明成員變量主要分析init方法賦值順序:

public class StackObserver {
    static class A {
        int a1 = 1;
        int a2 = 2;
        int a3;
        int a4;

        public A() {
            a3 = 3;
        }

        {
            a4 = 4;
        }

        int b(){
            return 1;
        }
    }

    public static void main(String[] args) {
        new A().b();
    }
}

通過IDE debug簡單分析下棧楨變化,new的時候init方法壓入棧楨栗涂,執(zhí)行b方法時init出棧知牌,b()壓入棧楨。如下圖:

棧楨變化

  1. init方法
    init方法是對象初始化的過程斤程,包括成員變量賦值角寸、對象代碼塊即{}、構(gòu)造方法拼接起來的初始化方法忿墅,拼接過程是由jvm幫我們做的扁藕。對應(yīng)還有一個class init方法,是在類加載階段執(zhí)行疚脐,包括類變量的賦值亿柑、類靜態(tài)代碼塊的執(zhí)行。

  2. 成員變量和全局變量是如何傳遞進(jìn)方法中的棍弄?
    這個問題之前學(xué)習(xí)jvm的時候真的沒有仔細(xì)思考過望薄,果然細(xì)節(jié)決定成敗。
    首先我們先思考下實(shí)例方法中呼畸,this變量是怎樣傳遞進(jìn)方法的作用域中的痕支。修改下代碼,如下:

public class StackObserver {
    static int GLOBAL = 4;
    static class A {
        ...
        int b(){
            return a1;
        }

        int c() {
            // 返回全局變量
            return GLOBAL;
        }
    }

    public static void main(String[] args) {
        // = new A().b();
        A a = new A(); 
        a.b();

        new A().c();
    }
}

this變量的傳遞我們需要先了解下局部變量表蛮原,它屬于棧楨的一部分卧须,用于傳遞變量,存儲單位為Slot儒陨、32位故慈,存儲類型包括java基本數(shù)據(jù)類型,即int float boolean char之類的框全,用1Slot存儲察绷,但double long用2Slot存儲,reference即對象引用津辩,用1Slot存儲拆撼。
在每個方法執(zhí)行時,方法棧楨都會附帶一個局部變量表喘沿,大小為jvm自動計(jì)算闸度,其中,Slot是可以復(fù)用的(減少不必要的內(nèi)存占用)蚜印。
回到原問題莺禁,我們可以猜測,成員變量的傳遞是通過this引用傳遞的窄赋,類變量是通過類引用變量傳遞的哟冬。通過查閱資料可知楼熄,在a調(diào)用b方法時,會將自身引用——this作為第0位Slot傳遞給b方法棧楨的局部變量表浩峡。
那么我們驗(yàn)證下猜測可岂,通過javac編譯源代碼得到class文件。

// 以下為編譯的class文件翰灾,而非java文件
public class StackObserver {
    static int GLOBAL = 4;

    public StackObserver() {
    }

    public static void main(String[] args) {
        StackObserver.A a = new StackObserver.A();
        a.b();
        (new StackObserver.A()).c();
    }

    static class A {
       ....
        int b() {
            return this.a1; // 猜測正確
        }

        int c() {
            return StackObserver.GLOBAL; // 猜測正確
        }
    }
}
  1. return語句執(zhí)行時缕粹,棧楨的變化
    將返回值壓入上層棧楨,這里的情景下上層棧楨是main()纸淮,如果有聲明局部變量賦值的話平斩,返回值會被記錄在局部變量表中;如沒有咽块,會被舍棄掉绘面。引用《JVM高級特性與最佳實(shí)踐》第八章的一段話。

方法退出
方法退出的過程實(shí)際上就等同于把當(dāng)前棧幀出棧糜芳,因此退出時可 能執(zhí)行的操作有:恢復(fù)上層方法的局部變量表和操作數(shù)棧,把返回值 (如果有的話)壓入調(diào)用者棧幀的操作數(shù)棧中魄衅,調(diào)整PC計(jì)數(shù)器的值以 指向方法調(diào)用指令后面的一條指令等峭竣。

3.總結(jié)

以上就是我個人對該問題的全部分析和總結(jié)啦,如果還沒了解過jvm的晃虫,強(qiáng)烈建議閱讀《JVM高級特性與最佳實(shí)踐》這本書皆撩,電子版pdf可以私我,還是希望大家支持正版哲银。
面試的時候我們也不必把所有細(xì)節(jié)都一一列舉出來扛吞,如上題,只要把涉及的知識點(diǎn)java內(nèi)存布局荆责、對象加載過程滥比、虛擬機(jī)執(zhí)行引擎(棧楨部分)簡單說下,然后選一個方向展開(這里可以是面試官的二次提問做院,也可以的個人延伸)盲泛,我在面試時由于對棧楨這部分細(xì)節(jié)掌握不好,就被問傻了键耕。寺滚。。
最后屈雄,分析問題時一定要自己好好思考村视。結(jié)論不是最重要的,思考的過程才是

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酒奶,一起剝皮案震驚了整個濱河市蚁孔,隨后出現(xiàn)的幾起案子奶赔,更是在濱河造成了極大的恐慌,老刑警劉巖勒虾,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纺阔,死亡現(xiàn)場離奇詭異,居然都是意外死亡修然,警方通過查閱死者的電腦和手機(jī)笛钝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愕宋,“玉大人玻靡,你說我怎么就攤上這事≈斜矗” “怎么了囤捻?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邻寿。 經(jīng)常有香客問我蝎土,道長,這世上最難降的妖魔是什么绣否? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任誊涯,我火速辦了婚禮,結(jié)果婚禮上蒜撮,老公的妹妹穿的比我還像新娘暴构。我一直安慰自己,他們只是感情好段磨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布取逾。 她就那樣靜靜地躺著,像睡著了一般苹支。 火紅的嫁衣襯著肌膚如雪砾隅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天债蜜,我揣著相機(jī)與錄音琉用,去河邊找鬼。 笑死策幼,一個胖子當(dāng)著我的面吹牛邑时,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播特姐,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼晶丘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浅浮,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤沫浆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后滚秩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體专执,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年郁油,在試婚紗的時候發(fā)現(xiàn)自己被綠了本股。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡桐腌,死狀恐怖拄显,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情案站,我是刑警寧澤躬审,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站蟆盐,受9級特大地震影響承边,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜石挂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一博助、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧誊稚,春花似錦翔始、人聲如沸罗心。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渤闷。三九已至疾瓮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間飒箭,已是汗流浹背狼电。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弦蹂,地道東北人肩碟。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像凸椿,于是被迫代替她去往敵國和親削祈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 工作之余,想總結(jié)一下JVM相關(guān)知識髓抑。 Java運(yùn)行時數(shù)據(jù)區(qū): Java虛擬機(jī)在執(zhí)行Java程序的過程中會將其管理的...
    Huang遠(yuǎn)閱讀 630評論 0 2
  • 一咙崎、運(yùn)行時數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個運(yùn)行時數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧吨拍、本地方法棧褪猛、堆、程序計(jì)數(shù)器羹饰,...
    加油小杜閱讀 1,514評論 1 15
  • 第二部分 自動內(nèi)存管理機(jī)制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運(yùn)行數(shù)據(jù)區(qū)域 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,138評論 0 2
  • 第6章類文件結(jié)構(gòu) 6.1 概述 6.2 無關(guān)性基石 6.3 Class類文件的結(jié)構(gòu) java虛擬機(jī)不和包括java...
    kennethan閱讀 913評論 0 2
  • 1伊滋、說說你知道的幾種主要的jvm參數(shù) -server -Xmx3g -Xms3g -XX:MaxPermSize=...
    夏與清風(fēng)閱讀 833評論 0 2