Q:簡單說說 Java 的 JVM 內(nèi)存結(jié)構(gòu)分為哪幾個部分? A:JVM 內(nèi)存共分為虛擬機棧、堆、方法區(qū)、程序計數(shù)器、本地方法棧,運行時常量池(六個部分,分別解釋如下)
Q: 堆和棧的特點當(dāng)在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,Java會自動釋放掉為該變量所分配的內(nèi)存空間,該內(nèi)存空間可以立即被另作他用。 堆內(nèi)存用來存放由new創(chuàng)建的對象和數(shù)組。 java中變量在內(nèi)存中的分配 1、類變量(static修飾的變量):在程序加載時系統(tǒng)就為它在堆中開辟了內(nèi)存,堆中的內(nèi)存地址存放于棧以便于高速訪問。靜態(tài)變量的生命周期--一直持續(xù)到整個'系統(tǒng)'關(guān)閉 2、實例變量:當(dāng)你使用java關(guān)鍵字new的時候,系統(tǒng)在堆中開辟并不一定是連續(xù)的空間分配給變量(比如說類實例),然后根據(jù)零散的堆內(nèi)存地址,通過哈希算法換算為一長串?dāng)?shù)字以表征這個變量在堆中的'物理位置'。 實例變量的生命周期--當(dāng)實例變量的引用丟失后,將被GC(垃圾回收器)列入可回收“名單”中,但并不是馬上就釋放堆中內(nèi)存 3、局部變量:局部變量,由聲明在某方法,或某代碼段里(比如for循環(huán)),執(zhí)行到它的時候在棧中開辟內(nèi)存,當(dāng)局部變量一但脫離作用域,內(nèi)存立即釋放 Q:你能不能談?wù)劊琷ava GC是在什么時候,對什么東西,做了什么事情? A:可參考前面分享的文章 「每日一面」怎么在面試時回答垃圾回收機制(GC)相關(guān)問題? Q:簡單談?wù)勀銓?Java 虛擬機內(nèi)存模型 JMM 的認識和理解及并發(fā)中的原子性、可見性、有序性的理解? 這是一個很泛很大且很有水準的面試題,也算是對并發(fā)基礎(chǔ)原理實質(zhì)的一個深度問題,想要在面試中簡短的回答好不是特別容易,本解析也僅供參考,具體理解可自己查閱其他資料。 Java 內(nèi)存模型主要目標是定義程序中變量(此處變量特指實例字段、靜態(tài)字段等,但不包括局部變量和函數(shù)參數(shù),因為這兩種是線程私有無法共享)在虛擬機中存儲到內(nèi)存與從內(nèi)存讀取出來的規(guī)則細節(jié),Java 內(nèi)存模型規(guī)定所有變量都存儲在主內(nèi)存中,每條線程還有自己的工作內(nèi)存,工作內(nèi)存保存了該線程使用到的變量到主內(nèi)存副本拷貝,線程對變量的所有操作(讀取、賦值)都必須在工作內(nèi)存中進行而不能直接讀寫主內(nèi)存中的變量,不同線程之間無法相互直接訪問對方工作內(nèi)存中的變量,線程間變量值的傳遞均需要在主內(nèi)存來完成(具體如下圖)。 Java 內(nèi)存模型對主內(nèi)存與工作內(nèi)存之間的具體交互協(xié)議定義了八種操作,具體如下:
如果要把一個變量從主內(nèi)存復(fù)制到工作內(nèi)存就必須按順序執(zhí)行 read 和 load 操作,從工作內(nèi)存同步回主內(nèi)存就必須順序執(zhí)行 store 和 write 操作,但是 JVM 只要求了操作的順序而沒有要求上述操作必須保證連續(xù)性,所以實質(zhì)執(zhí)行中 read 和 load 間及 store 和 write 間是可以插入其他指令的。 Java 內(nèi)存模型還會對指令進行重排序操作,在執(zhí)行程序時為了提高性能編譯器和處理器經(jīng)常會對指令進行重排序操作,重排序主要分下面幾類:
其實 Java JMM 內(nèi)存模型是圍繞并發(fā)編程中原子性、可見性、有序性三個特征來建立的,關(guān)于原子性、可見性、有序性的理解如下:
|
|
來自: 太極混元天尊 > 《學(xué)習(xí)資料》