一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

「每日一面」面試中對Java 內(nèi)存結(jié)構(gòu)的認識

 太極混元天尊 2018-06-12

Q:簡單說說 Java 的 JVM 內(nèi)存結(jié)構(gòu)分為哪幾個部分?

A:JVM 內(nèi)存共分為虛擬機棧、堆、方法區(qū)、程序計數(shù)器、本地方法棧,運行時常量池(六個部分,分別解釋如下)

  • 虛擬機棧:

    線程私有的,每個方法在執(zhí)行時會創(chuàng)建一個棧幀,用來存儲局部變量表、操作數(shù)棧、動態(tài)連接、方法返回地址等;其中局部變量表用于存放 8 種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)和 reference 類型。每個方法從調(diào)用到執(zhí)行完畢對應(yīng)一個棧幀在虛擬機棧中的入棧和出棧。
  • 堆:

    線程共享的,在虛擬機啟動時創(chuàng)建,用于存放對象實例。
  • 方法區(qū):

    線程共享的,用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量等。
  • 程序計數(shù)器:

    線程私有的,是當(dāng)前線程所執(zhí)行的字節(jié)碼行號指示器,每個線程都有一個獨立的程序計數(shù)器,字節(jié)碼解釋器工作時通過改變它的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理和線程恢復(fù)都依賴于它。
  • 本地方法棧:

    線程私有的,主要為虛擬機用到的 native 方法服務(wù),與虛擬機棧類似。
  • 運行時常量池(Runtime Constant Pool)

    ,存放的為類中的固定的常量信息、方法和Field的引用信息等,其空間從方法區(qū)域中分配。

「每日一面」面試中對Java 內(nèi)存結(jié)構(gòu)的認識

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)存結(jié)構(gòu)的認識

Java 內(nèi)存模型對主內(nèi)存與工作內(nèi)存之間的具體交互協(xié)議定義了八種操作,具體如下:

  • lock(鎖定):作用于主內(nèi)存變量,把一個變量標識為一條線程獨占狀態(tài)。
  • unlock(解鎖):作用于主內(nèi)存變量,把一個處于鎖定狀態(tài)的變量釋放出來,釋放后的變量才可以被其他線程鎖定。
  • read(讀?。鹤饔糜谥鲀?nèi)存變量,把一個變量從主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的 load 動作使用。
  • load(載入):作用于工作內(nèi)存變量,把 read 操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中。
  • use(使用):作用于工作內(nèi)存變量,把工作內(nèi)存中的一個變量值傳遞給執(zhí)行引擎,每當(dāng)虛擬機遇到一個需要使用變量值的字節(jié)碼指令時執(zhí)行此操作。
  • assign(賦值):作用于工作內(nèi)存變量,把一個從執(zhí)行引擎接收的值賦值給工作內(nèi)存的變量,每當(dāng)虛擬機遇到一個需要給變量進行賦值的字節(jié)碼指令時執(zhí)行此操作。
  • store(存儲):作用于工作內(nèi)存變量,把工作內(nèi)存中一個變量的值傳遞到主內(nèi)存中,以便后續(xù) write 操作。
  • write(寫入):作用于主內(nèi)存變量,把 store 操作從工作內(nèi)存中得到的值放入主內(nèi)存變量中。

如果要把一個變量從主內(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)常會對指令進行重排序操作,重排序主要分下面幾類:

  • 編譯器優(yōu)化重排序:編譯器在不改變單線程程序語義的前提下可以重新安排語句的執(zhí)行順序。
  • 指令級并行重排序:現(xiàn)代處理器采用了指令級并行技術(shù)來將多條指令重疊執(zhí)行,如果不存在數(shù)據(jù)依賴性處理器可以改變語句對應(yīng)機器指令的執(zhí)行順序。
  • 內(nèi)存系統(tǒng)重排序:由于處理器使用緩存和讀寫緩沖區(qū)使得加載和存儲操作看上去可能是在亂序執(zhí)行。

其實 Java JMM 內(nèi)存模型是圍繞并發(fā)編程中原子性、可見性、有序性三個特征來建立的,關(guān)于原子性、可見性、有序性的理解如下:

  • 原子性:就是說一個操作不能被打斷,要么執(zhí)行完要么不執(zhí)行,類似事務(wù)操作,Java 基本類型數(shù)據(jù)的訪問大都是原子操作,long 和 double 類型是 64 位,在 32 位 JVM 中會將 64 位數(shù)據(jù)的讀寫操作分成兩次 32 位來處理,所以 long 和 double 在 32 位 JVM 中是非原子操作,也就是說在并發(fā)訪問時是線程非安全的,要想保證原子性就得對訪問該數(shù)據(jù)的地方進行同步操作,譬如 synchronized 等。
  • 可見性:就是說當(dāng)一個線程對共享變量做了修改后其他線程可以立即感知到該共享變量的改變,從 Java 內(nèi)存模型我們就能看出來多線程訪問共享變量都要經(jīng)過線程工作內(nèi)存到主存的復(fù)制和主存到線程工作內(nèi)存的復(fù)制操作,所以普通共享變量就無法保證可見性了;Java 提供了 volatile 修飾符來保證變量的可見性,每次使用 volatile 變量都會主動從主存中刷新,除此之外 synchronized、Lock、final 都可以保證變量的可見性。
  • 有序性:就是說 Java 內(nèi)存模型中的指令重排不會影響單線程的執(zhí)行順序,但是會影響多線程并發(fā)執(zhí)行的正確性,所以在并發(fā)中我們必須要想辦法保證并發(fā)代碼的有序性;在 Java 里可以通過 volatile 關(guān)鍵字保證一定的有序性,還可以通過 synchronized、Lock 來保證有序性,因為 synchronized、Lock 保證了每一時刻只有一個線程執(zhí)行同步代碼相當(dāng)于單線程執(zhí)行,所以自然不會有有序性的問題;除此之外 Java 內(nèi)存模型通過 happens-before 原則如果能推導(dǎo)出來兩個操作的執(zhí)行順序就能先天保證有序性,否則無法保證,關(guān)于 happens-before 原則可以查閱相關(guān)資料。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美日不卡无在线一区| 欧美尤物在线视频91| 黄色片一区二区三区高清| 国产精品欧美激情在线观看| 欧美日韩免费黄片观看| 亚洲欧美日韩另类第一页| 三级高清有码在线观看| 欧美久久一区二区精品| 国产视频福利一区二区| 老鸭窝老鸭窝一区二区| 欧美乱妇日本乱码特黄大片 | 十八禁日本一区二区三区| 高清一区二区三区大伊香蕉| 成人午夜激情免费在线| 香蕉久久夜色精品国产尤物| 久久热中文字幕在线视频| 国语对白刺激高潮在线视频| 国产真人无遮挡免费视频一区 | 老司机精品视频免费入口| 亚洲天堂男人在线观看| 欧美精品久久男人的天堂| 日本理论片午夜在线观看| 亚洲国产成人精品一区刚刚| 色婷婷国产熟妇人妻露脸| 视频一区二区三区自拍偷| 夫妻性生活一级黄色录像| 国内精品一区二区欧美| 国产精品尹人香蕉综合网| 国产成人精品99在线观看| 亚洲一区二区精品国产av| 四季精品人妻av一区二区三区| 久久亚洲精品成人国产| 黄片美女在线免费观看| 精品高清美女精品国产区| 色婷婷中文字幕在线视频| 麻豆印象传媒在线观看| 青青操在线视频精品视频| 午夜精品一区二区av| 欧美日韩无卡一区二区| 国产成人亚洲精品青草天美| 亚洲内射人妻一区二区|