日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
聊聊JVM基礎(chǔ),快進(jìn)來(lái)復(fù)習(xí)復(fù)習(xí)吧

 大家好,今天總結(jié)了一下老生常談的 JVM,這也是面試必問(wèn)的知識(shí)。

創(chuàng)新互聯(lián)建站為企業(yè)級(jí)客戶提高一站式互聯(lián)網(wǎng)+設(shè)計(jì)服務(wù),主要包括網(wǎng)站制作、成都做網(wǎng)站app軟件開(kāi)發(fā)公司、微信小程序定制開(kāi)發(fā)、宣傳片制作、LOGO設(shè)計(jì)等,幫助客戶快速提升營(yíng)銷能力和企業(yè)形象,創(chuàng)新互聯(lián)各部門都有經(jīng)驗(yàn)豐富的經(jīng)驗(yàn),可以確保每一個(gè)作品的質(zhì)量和創(chuàng)作周期,同時(shí)每年都有很多新員工加入,為我們帶來(lái)大量新的創(chuàng)意。 

話不多說(shuō),整起來(lái)!

一、JVM 是什么?

1、Java 虛擬機(jī)(Jvm)是可運(yùn)行 Java 代碼的假想計(jì)算機(jī)。

2、Jvm 充當(dāng)著一個(gè)翻譯官的角色,我們平常所編寫出的 Java 程序,是不能夠被操作系統(tǒng)所直接識(shí)別的,這時(shí)候 JVM 的作用就體現(xiàn)出來(lái)了,它負(fù)責(zé)把我們的程序翻譯給系統(tǒng)“聽(tīng)”,告訴它我們的程序需要做什么操作。

3、Jvm 針對(duì)每個(gè)操作系統(tǒng)開(kāi)發(fā)其對(duì)應(yīng)的解釋器,所以只要其操作系統(tǒng)有對(duì)應(yīng)版本的 Jvm,那么這份 Java 編譯后的代碼就能夠運(yùn)行起來(lái),有句話大家一定聽(tīng)說(shuō)過(guò):「Java 能一次編譯到處運(yùn)行」,這就是原因所在。

二、Jvm 的體系架構(gòu)?

Jvm 是這四部分組成:

  • 運(yùn)行區(qū)數(shù)據(jù)
  • 類加載器
  • 執(zhí)行引擎
  • 垃圾回收器

下面就聊聊這四個(gè)部分~~

2.1 運(yùn)行區(qū)數(shù)據(jù)

Java 虛擬機(jī)在執(zhí)行 Java 程序的過(guò)程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域,這些區(qū)域各有各的作用,各有各的生命周期。

有些區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有些區(qū)域則依賴用戶線程的啟動(dòng)和結(jié)束建立和銷毀。

運(yùn)行區(qū)數(shù)據(jù)的劃分:方法區(qū)、虛擬機(jī)棧,本地方法棧、堆、程序計(jì)數(shù)器

上面這張圖大家一定都見(jiàn)過(guò),其實(shí)可以劃分的更細(xì)點(diǎn),看下面的這兩張圖:

能看出 1.8 版本前后的差別么,下面就看看這些區(qū)域都干啥的~~

程序計(jì)數(shù)器

  • 其實(shí)你可以把它看作是當(dāng)前線程執(zhí)行的字節(jié)碼的行號(hào)指示器,在 Jvm 工作時(shí),就是通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán),跳轉(zhuǎn),異常處理,線程的恢復(fù)等工作都需要依賴程序計(jì)數(shù)器去完成。它就好像是一個(gè)路口的紅綠燈一樣。

特點(diǎn):1、占用很小的內(nèi)存 2、各線程私有

就比如下面字節(jié)碼一樣,每一行開(kāi)頭的黃色數(shù)字,我們就可以認(rèn)為它是程序計(jì)數(shù)器所存儲(chǔ)的內(nèi)容:

 
 
 
 
  1. public void doSth1();
  2.    descriptor: ()V
  3.    flags: ACC_PUBLIC
  4.    Code:
  5.      stack=2, locals=3, args_size=1
  6.         0: ldc           #5
  7.         2: dup
  8.         3: astore_1
  9.         4: monitorenter
  10.         5: getstatic     #2
  11.         8: ldc           #3
  12.        10: invokevirtual #4
  13.        13: aload_1

虛擬機(jī)棧

  • 虛擬機(jī)棧,其描述的就是線程內(nèi)存模型,也可以稱作線程棧,也是每個(gè)線程私有的,生命周期與線程保持一致。在每個(gè)方法執(zhí)行的時(shí)候,jvm 都會(huì)同步創(chuàng)建一個(gè)棧幀去存儲(chǔ)局部變量表,操作數(shù)棧,動(dòng)態(tài)連接,方法出口等信息。一個(gè)方法的生命周期就貫徹了一個(gè)棧幀從入棧到出棧的全部過(guò)程。

特點(diǎn):1、隨線程而生、隨線程而死 2、先進(jìn)后出

棧示意圖:

本地方法棧

  • 本地方法棧,和虛擬棧其實(shí)很相似的,我們知道,java 底層用了很多 c 的代碼去實(shí)現(xiàn),而其調(diào)用 c 端的方法上都會(huì)有 native 來(lái)代表本地方法,而本地方法棧就是為其服務(wù)的。

特點(diǎn):1、各線程私有 2、和本地方法有關(guān)

native 修飾的方法:

 
 
 
 
  1. public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

  1. 堆可以說(shuō)是 jvm 中最大的一塊內(nèi)存區(qū)域了,它是所有線程共享,幾乎所有的對(duì)象實(shí)例都會(huì)在這里分配。
  2. java 堆是垃圾回收器主要回收的區(qū)域。從內(nèi)存回收的角度來(lái)說(shuō),堆空間可以分為新生代和老年代,而新生代又可以分為伊甸區(qū),Survivor 區(qū)。

特點(diǎn):1、所有線程共享 2、占用大的內(nèi)存空間 3、先進(jìn)先出

堆的劃分:

方法區(qū)

  1. 方法區(qū),也是各個(gè)線程共享的內(nèi)存區(qū)域,它是用來(lái)被存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯后的代碼等數(shù)據(jù)。
  2. 從上面的圖,可以看到 1.8 之前和之后,方法區(qū)所在的位置是有差別的。在 Java 8 之前有個(gè)永久代的概念,實(shí)際上指的是 HotSpot 虛擬機(jī)上的永久代,它用永久代實(shí)現(xiàn)了 JVM 規(guī)范定義的方法區(qū)功能,這部分由于是在堆中實(shí)現(xiàn)的,受 GC 的管理,不過(guò)由于永久代有 -XX:MaxPermSize 的上限,所以如果大量地調(diào)用 String.intern 方法 (將字段串放入永久代中的常量區(qū))或 動(dòng)態(tài)生成類(將類信息放入永久代),很容易造成 OOM。
  3. 所以,在 Java 8 中就把方法區(qū)的實(shí)現(xiàn)移到了本地內(nèi)存中的元空間中,這樣方法區(qū)就不受 JVM 的控制了,這個(gè)區(qū)域也就不會(huì)進(jìn)行 GC,也因此提升了性能,正因?yàn)榉诺搅吮镜貎?nèi)存,也就不存在由于永久代限制大小而導(dǎo)致的 OOM 異常了。
  4. 另外,運(yùn)行時(shí)常量池也是方法區(qū)的一部分,用來(lái)存放編譯期生成的各種字面量和符號(hào)引用,這部分內(nèi)容在類加載后進(jìn)入該常量池中。

特點(diǎn):1、所有線程共享 2、1.8 之后移到了元空間 3、涉及到常量池

直接內(nèi)存

從上面的圖中,看到有直接內(nèi)存這個(gè)區(qū)域

  • 直接內(nèi)存,并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,其實(shí)可以理解為堆外內(nèi)存,在一些場(chǎng)景下,比如:NIO 類引入了一種基于通道(Channel)與緩沖區(qū)(Buffer)的 IO 方式,它可以使用 Native 函數(shù)庫(kù)直接分配堆外內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ) Java 堆中的對(duì)象作為這塊內(nèi)存的引用,這樣能夠顯著提高性能,因?yàn)楸苊饬?Java 堆和 Native 堆中來(lái)回復(fù)制數(shù)據(jù)。

2.2 類加載器

1、什么是類加載機(jī)制?

JVM 運(yùn)行時(shí),java 虛擬機(jī)會(huì)把描述類的數(shù)據(jù)從 Class 文件加載到內(nèi)存,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換、解析和初始化,最終形成可以被 jvm 可以直接使用的類型,這就是類加載機(jī)制。

2、說(shuō)說(shuō)類加載的過(guò)程?

開(kāi)局一張圖:

這張圖說(shuō)明了類從加載到虛擬機(jī)內(nèi)存開(kāi)始,到卸載出內(nèi)存為止,它的整個(gè)生命周期。

一般來(lái)說(shuō),我們把 Java 的類加載過(guò)程分為三個(gè)主要步驟:加載、鏈接、初始化,具體行為在 Java 虛擬機(jī)規(guī)范里有非常詳細(xì)的定義。

1、首先是加載階段

  1. 它是 Java 將字節(jié)碼(jar 包)數(shù)據(jù)從不同的數(shù)據(jù)源讀取到 JVM 中,并映射為 JVM 認(rèn)可的數(shù)據(jù)結(jié)構(gòu)(Class 對(duì)象),
  2. 重點(diǎn):加載階段是用戶參與的階段,我們可以自定義類加載器,去實(shí)現(xiàn)自己的類加載過(guò)程。
  3. 通過(guò)字節(jié)流將類的.class 文件中的二進(jìn)制數(shù)據(jù)讀入到內(nèi)存。然后在堆中創(chuàng)建 java.lang.class 對(duì)象,用來(lái)封裝類在方法區(qū)的數(shù)據(jù)結(jié)構(gòu)
  4. 只會(huì)創(chuàng)建一個(gè) Class 對(duì)象,該 Class 對(duì)象來(lái)描述有哪些構(gòu)造方法,都有哪些成員變量

2、第二階段是鏈接,這是核心的步驟,簡(jiǎn)單說(shuō)是把原始的類定義信息平滑地轉(zhuǎn)化入 JVM 運(yùn)行的過(guò)程中。這里可進(jìn)一步細(xì)分為三個(gè)步驟:

① 驗(yàn)證

  1. 這是虛擬機(jī)安全的重要保障,JVM 需要核驗(yàn)字節(jié)信息是符合 Java 虛擬機(jī)規(guī)范的,否則就被認(rèn)為是 VerifyError,這樣就防止了惡意信息或者不合規(guī)的信息危害 JVM 的運(yùn)行,
  2. 驗(yàn)證階段有可能觸發(fā)更多 class 的加載。

② 準(zhǔn)備

  1. 創(chuàng)建類或接口中的靜態(tài)變量,并初始化靜態(tài)變量的初始值。
  2. 但這里的“初始化”和下面的顯式初始化階段是有區(qū)別的,
  3. 測(cè)重點(diǎn)在于分配需要的內(nèi)存空間,不會(huì)去執(zhí)行更進(jìn)一步的 JVM 指令

這里的初始化是指:

1、8 種基本數(shù)據(jù)類型的默認(rèn)初始值是 0。

2、引用類型默認(rèn)的初始值是 null。

3、對(duì)于有 static final 修飾的常量會(huì)直接賦值,例如:static final int x=123;則 x 直接會(huì)初始化為 123。

③ 解析

  1. 在這一步會(huì)將常量池中的符號(hào)引用(symbolic reference)替換為直接引用。
  2. 符號(hào)引用就是唯一的字符串,直接引用可以理解為一個(gè)地址值和偏移量

3、最后是初始化階段

這一步真正去執(zhí)行類初始化的代碼邏輯,包括靜態(tài)字段動(dòng)作,以及執(zhí)行類定定義中的靜態(tài)初始化塊內(nèi)的邏輯編譯器在編譯階段就會(huì)把這部分邏輯整理好,父類型的初始化邏輯優(yōu)先于當(dāng)前類型的邏輯。

初始化順序:

  • 先是父類靜態(tài)域(靜態(tài)成員變量)或者靜態(tài)代碼庫(kù)塊
  • 然后是子類靜態(tài)域或者子類靜態(tài)代碼塊
  • 所以最先初始化的總是 java.lang.Object 類

三、什么時(shí)候會(huì)對(duì)類進(jìn)行初始化?

通過(guò) new 關(guān)鍵字實(shí)例化對(duì)象、讀取或設(shè)置類的靜態(tài)變量、調(diào)用類的靜態(tài)方法

通過(guò)反射發(fā)生上面的三種行為

初始化子類時(shí),會(huì)觸發(fā)父類的初始化

作為程序入口運(yùn)行,就是指的 main 方法

四、類加載器有哪些?

啟動(dòng)類加載器:負(fù)責(zé)加載環(huán)境變量下 jre/lib 下面的 jar 文件

擴(kuò)展類加載器:負(fù)責(zé)加載環(huán)境變量下 jre/lib/ext 目錄下面的 jar 包

應(yīng)用類加載器:就是加載我們熟悉的 classpath 的內(nèi)容

自定義加載器:繼承 ClassLoader 就可以實(shí)現(xiàn)

五、了解雙親委派模型嗎?

這是一張很經(jīng)典的圖,通常情況下,各個(gè)類加載器的協(xié)作關(guān)系就是這樣的。

概念:就是說(shuō)一個(gè)類加載器收到了類加載的請(qǐng)求,不會(huì)自己先加載,而是把它交給自己的父類去加載,層層迭代。

用上圖來(lái)說(shuō)明就是如果應(yīng)用程序類加載器收到了一個(gè)類加載的請(qǐng)求,會(huì)先給擴(kuò)展類加載器,然后再給啟動(dòng)類加載器,如果啟動(dòng)類加載器無(wú)法完成這個(gè)類加載的請(qǐng)求,再返回給擴(kuò)展類加載器,如果擴(kuò)展類加載器也無(wú)法完成,最后才會(huì)到應(yīng)用類加載器。

好處:1、避免重復(fù)加載 Java 類型 2、沙箱安全機(jī)制:保證核心的類不會(huì)被篡改。

六、classLoader與class.forName區(qū)別

  • class.forName()除了將類的.class 文件加載到 jvm 中之外,還會(huì)對(duì)類進(jìn)行解釋,執(zhí)行類中的 static 塊,當(dāng)然你可以指定是否執(zhí)行靜態(tài)塊。
  • classLoader 只干一件事情,就是將.class 文件加載到 jvm 中,不會(huì)執(zhí)行 static 中的內(nèi)容,只有在 newInstance 才會(huì)去執(zhí)行 static 塊。

七、腦圖

最后送大家一張自己總結(jié)的腦圖呀

今天就寫到這里啦!!

給大家介紹了JVM、運(yùn)行區(qū)數(shù)據(jù)、類加載機(jī)制。希望大家面試前能掌握和Jvm有關(guān)的知識(shí)。


網(wǎng)站題目:聊聊JVM基礎(chǔ),快進(jìn)來(lái)復(fù)習(xí)復(fù)習(xí)吧
本文來(lái)源:http://m.5511xx.com/article/djpdjds.html