JVM知識回顧

JVM知識回顧

1. 簡述JDK,JRE和JVM之間的關(guān)系

jdk架構(gòu)
  • JDK:

    • 是用于支持Java程序開發(fā)的最小環(huán)境例隆,基本上Java程序設(shè)計語言埂软、Java虛擬機么介、Java API類庫這三部分

    • JDK=JRE+java開發(fā)工具包

    • 作用:java程序的開發(fā)環(huán)境

  • JRE:

    • 是支持Java程序運行的標準環(huán)境拧咳,Java API類庫中的Java SE API自己和Java虛擬機這兩部分

    • java運行環(huán)境=JVM+核心類庫

    • 作用:java程序的運行環(huán)境

  • JVM:

    • 保證 Java程序設(shè)計語言的安全特性和java語言的跨平臺性
    • 一次編譯诞挨,到處運行(Write once,run anywhere)

    簡言之底靠,使用 jdk 開發(fā)的java程序揽趾,交由 JRE 來運行,由 JVM 來保證跨平臺

2. 類加載機制的作用和過程

一句話解釋:類的加載指的是將.class文件中的二進制數(shù)讀入到內(nèi)存中苛骨,將其放在運行數(shù)據(jù)區(qū)的方法區(qū)內(nèi)篱瞎,然后在堆區(qū)創(chuàng)建一個java.lang.Class對象,用來封裝類在方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)痒芝。
類的生命周期

類的加載過程包括加載俐筋、驗證、準備严衬、解析澄者、初始化五個階段

1)加載

? 在加載階段,虛擬機主要做了三件事

  1. 通過一個類的全限定類名來獲取其定義的二進制字節(jié)流
  2. 將這個字節(jié)流代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)
  3. 在堆中生成一個代表這個類的Class對象请琳,作為方法區(qū)中這些數(shù)據(jù)的訪問入口

2)驗證

? 保證被加載類的準確性

  1. 文件格式的驗證:驗證.class文件字節(jié)流是否符合class文件的格式規(guī)范粱挡,并且能夠被當前版本的虛擬機處理。這里主要對魔數(shù)俄精、主版本號询筏、常量池等等的校驗
  2. 元數(shù)據(jù)驗證:主要對字節(jié)碼描述的信息進行語義分析,以保證其描述的信息符合java語言規(guī)范的要求竖慧。比如說驗證這個類是不是有父類嫌套,類中的字段方法是不是和父類有沖突
  3. 字節(jié)碼驗證:這是整個驗證過程中最復(fù)雜的階段逆屡,主要是通過數(shù)據(jù)流和控制流分析,確定程序語義是合法的踱讨、符合邏輯的魏蔗。在元數(shù)據(jù)驗證階段對數(shù)據(jù)類型做出驗證后,這個階段主要對類的方法做出分析痹筛,保證類的方法在運行時不會做出危害虛擬機的事莺治。
  4. 符號引用驗證:他是驗證的最后一個階段,發(fā)生在虛擬機將符號引用轉(zhuǎn)化為直接引用的時候帚稠。主要是對類自身以外的信息進行校驗谣旁。目的是確保解析動作能夠完成。

3)準備

? 準備階段主要為類變量分配內(nèi)存并設(shè)置初始值

  1. 類變量(static)會分配內(nèi)存翁锡,但實例變量不會蔓挖,實例變量主要隨著對象的實例化一塊分配到j(luò)ava堆中

  2. 這里的初始值值得是數(shù)據(jù)類型默認值夕土,不是代碼中被顯示賦予的值馆衔。比如

    public static int a = 1;
    

    這里的a在準備階段過后值為0,而不是1怨绣。賦值為1的動作在初始化階段角溃。

4)解析

? 解析階段主要是虛擬機將常量池中的符號引用轉(zhuǎn)為直接引用的過程

  • 符號引用:以一組符號來描述所引用的目標,可以是任何形式的字面量篮撑。classfile中的內(nèi)容减细,沒有實際含義
  • 直接引用:直接引用是可以指向目標的指針、相對偏移量或者是一個能直接或間接定位到目標的句柄赢笨。和虛擬機實現(xiàn)的內(nèi)存有關(guān)未蝌,不同的虛擬機直接引用一般不同。在java進程中能夠代表真實含義的

5)初始化

? 主要為類的靜態(tài)變量賦予正確的初始值茧妒,有兩種方式

  1. 聲明類變量時指定初始值
  2. 使用靜態(tài)代碼塊為類變量指定初始值

3. 運行時數(shù)據(jù)區(qū)分為哪幾塊?說說你對每塊區(qū)域的理解(某些存儲的內(nèi)容,生命周期,作用等)

運行時數(shù)據(jù)區(qū)

? 運行時數(shù)據(jù)區(qū)分為方法區(qū)萧吠、堆、虛擬機棧桐筏、本地方法棧纸型、程序計數(shù)器

  1. 程序計數(shù)器:線程私有,可以看成是當前線程所執(zhí)行的字節(jié)碼的行號指示器梅忌,用于選取下一條需要執(zhí)行的指令狰腌,也是唯一一個沒有OOM情況的區(qū)域,與線程共存亡
  2. Java虛擬機棧:線程私有牧氮,為JVM執(zhí)行Java方法服務(wù)琼腔,主要描述Java方法執(zhí)行的線程內(nèi)存模型,與線程共存亡
  3. 本地方法棧:線程私有踱葛,與虛擬機棧相似展姐,為JVM使用到的Native方法服務(wù)躁垛,Native方法多用C++寫
  4. Java堆:線程共享,主要用于存儲實例對象圾笨,Java中幾乎所有的對象實例都會存儲到這塊內(nèi)存中教馆,考慮到即時編譯和逃逸分析,有一部分的對象實例會分配到棧上
  5. 方法區(qū):線程共享擂达,主要用于存儲被JVM加載的類信息土铺、常量、靜態(tài)變量板鬓、即時編譯器編譯后的代碼緩存等數(shù)據(jù)
  6. 運行時常量池:線程共享悲敷,屬于方法區(qū)的一部分,用于存放編譯期生成的各種字面量和符號引用

4. 結(jié)合Eden,S0,S1和Old區(qū),描述一下一個對象創(chuàng)建的過程

? 對象的分配俭令,從理論上來講應(yīng)該都是在堆上分配(即時編譯和逃逸分析后德,會分配到棧上)。在正常分代的情況中抄腔,新生成的對象會分配在新生代中瓢湃,但是少數(shù)情況下(比如對象大小超過一定閾值)會直接分配到老年代。

? 大多數(shù)情況下赫蛇,對象在Eden區(qū)中分配绵患,當Eden區(qū)沒有足夠空間時,虛擬機會發(fā)起一次Minor GC悟耘,新生代采用的是復(fù)制算法落蝙,把存活的對象從Eden和S0復(fù)制到S1區(qū),后把對象年齡加一暂幼,并清空Eden和S0(新生代的對象大多為活躍的對象筏勒,會頻繁的創(chuàng)建和銷毀,所以新生代GC時應(yīng)該存活的對象很少旺嬉,所以采用復(fù)制算法是最合適的)管行。當對象達到一定年齡之后(默認15歲,可修改-XX:MaxTenuringThresold=需要的年齡數(shù)字)鹰服,對象會被移動到老年代病瞳,當然老年代如果空間不足,會發(fā)生Major GC悲酷,采用標記整理算法(老年代的對象大部分都是經(jīng)過一段Minor GC的套菜,所以相對比較穩(wěn)定,每次回收的對象相對比較少设易,所以采用標記整理算法最合適)。
? 另外戏溺,一個對象的創(chuàng)建過程旷祸,上述描述只是一個對象的創(chuàng)建過程中的一個步驟中的詳解耕拷,一個對象的創(chuàng)建,從虛擬機的角度來看托享,包括:遇到new指令—判斷引用能否在常量池定位骚烧;檢查引用能否被加載、解析闰围、初始化過—分配內(nèi)存(包括指針碰撞和空閑列表法赃绊,這一部分內(nèi)容是我上面的描述)—初始化內(nèi)存空間—設(shè)置對象頭—執(zhí)行init()方法碧查。

5. 怎樣確定一個對象為垃圾

  1. 引用計數(shù)法

    ? 引用計數(shù)算法就是在對象中添加了一個引用計數(shù)器,當有地方引用這個對象時校仑,引用計數(shù)器的值就加1忠售,當引用失效的時候,引用計數(shù)器的值就減1邢滑。當引用計數(shù)器的值為0時,jvm就開始回收這個對象愿汰。

    簡單的來說困后,在JVM中的棧中,如果棧幀中指向了一個對象衬廷,那么堆中的引用計數(shù)器的值就會加1摇予,當棧幀這個指向null時,對象的引用計數(shù)器就減1吗跋。

    ? 這種方法雖然很簡單侧戴、高效,但是JVM一般不會選擇這個方法跌宛,因為這個方法會出現(xiàn)一個問題:當對象之間相互指向時酗宋,兩個對象的引用計數(shù)器的值都會加1,而由于兩個對象時相互指向疆拘,所以引用不會失效蜕猫,這樣JVM就無法回收。

  2. 可達性分析法(Reachability Analysis)
    所有生成的對象都是一個稱為"GC Roots"的根的子樹哎迄。從GC Roots開始向下搜索回右,搜索所經(jīng)過的路徑稱為引用鏈(Reference Chain)隆圆,當一個對象到“GC Roots”沒有任何引用鏈可以到達時,就稱這個對象是不可達的(不可引用的)翔烁,也就是可以被GC回收了渺氧。

可達性分析法

6. 常用的垃圾回收算法有哪些?有什么優(yōu)缺點

  1. **標記-清除 **

    ? 分為兩個階段:標記和清除。根據(jù)根節(jié)點可達分析哪些對象為垃圾蹬屹,并對垃圾進行標記阶女,然后統(tǒng)一回收。這是最基礎(chǔ)的算法哩治,后續(xù)的收集算法都是基于這個算法擴展的秃踩。

    不足:

    • 掃描整個堆內(nèi)存,耗時业筏,效率低憔杨;

    • 標記清除之后會產(chǎn)生大量碎片。

  2. 標記整理

    ? 分為兩個階段:標記和整理蒜胖。根據(jù)根節(jié)點可達分析哪些對象為垃圾消别,并對垃圾進行標記,將還在被使用的對象移動到一端台谢。然后在清理掉這個范圍之外的垃圾寻狂。

    優(yōu)點:

    • 避免了內(nèi)存碎片

    缺點:

    • 整理內(nèi)存耗時
  3. 復(fù)制

    ? 將內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中一塊朋沮,當這一塊內(nèi)存用完蛇券,將還在被使用的對象復(fù)制到另一塊上,再將已使用過的那一塊內(nèi)存空間全部清理掉樊拓。

    優(yōu)點:

    • 效率高纠亚,實現(xiàn)簡單

    缺點:

    • 內(nèi)存空間利用率只用50%

7. 簡述你對吞吐量和停頓時間的理解

? 在實踐活動中,我們通過最優(yōu)吞吐量和最短停頓時間來評價jvm系統(tǒng)的性能:

? 吞吐量越高算法越好
? 暫停時間越短算法越好
? 首先讓我們來明確垃圾收集(GC)中的兩個術(shù)語:吞吐量(throughput)和暫停時間(pause times)筋夏。 JVM在專門的線程(GC threads)中執(zhí)行GC蒂胞。只要GC線程是活動的,它們將與應(yīng)用程序線程(application threads)爭用當前可用CPU的時鐘周期条篷。簡單點來說骗随,吞吐量是指應(yīng)用程序線程用時占程序總用時的比例。例如赴叹,吞吐量99/100意味著100秒的程序執(zhí)行時間應(yīng)用程序線程運行了99秒鸿染,而在這一時間段內(nèi)GC線程只運行了1秒。
? 術(shù)語”暫停時間”是指一個時間段內(nèi)應(yīng)用程序線程讓與GC線程執(zhí)行而完全暫停稚瘾。例如牡昆,GC期間100毫秒的暫停時間意味著在這100毫秒期間內(nèi)沒有應(yīng)用程序線程是活動的。 如果說一個正在運行的應(yīng)用程序有100毫秒的“平均暫停時間”,那么就是說該應(yīng)用程序所有的暫停時間平均長度為100毫秒丢烘。同樣柱宦,100毫秒的“最大暫停時間”是指該應(yīng)用程序所有的暫停時間最大不超過100毫秒。

8. 常見的jdk命令和工具有什么?并簡述一下他們的作用

? 常見的jdk命令:

  • jps

    jps是JVM Process Status Tool的簡稱播瞳,用于顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機進程掸刊。常用的命令有:

    jps -l //用于輸出主類的全名,如果運行的是jar包赢乓,則輸出jar路徑忧侧;

    jps -v //用于輸出虛擬機啟動時的JVM參數(shù)。

    [qianfg@Centos7 ~]$ jps -l
    6563 eurekaserver-0.0.1-SNAPSHOT.jar
    6564 manage-0.0.1-SNAPSHOT.war
    6565 mybank-0.0.1-SNAPSHOT.war
    6567 overseas-0.0.1-SNAPSHOT.war
    5639 sun.tools.jps.Jps
    17898 org.apache.rocketmq.namesrv.NamesrvStartup
    17900 org.apache.rocketmq.broker.BrokerStartup
    22783 org.apache.catalina.startup.Bootstrap
    
  • jstat

    jstat是JVM Statistics Monitoring Tool的簡稱牌芋,用于顯示本地或遠程虛擬機進程中的類加載蚓炬、內(nèi)存、垃圾回收躺屁、JIT編譯等運行時數(shù)據(jù)肯夏。

    jstat -class pid //類裝載信息

    [qianfg@Centos7 ~]$ jstat -class 6563
    Loaded  Bytes  Unloaded  Bytes     Time
     11234 19528.8        0     0.0      60.17
    
  • jinfo

    jinfo是Configuration Info for Java的簡稱,用于顯示虛擬機各項參數(shù)犀暑。常用的命令有:

    jinfo -flag pid //用于查看未被顯示指定的參數(shù)的默認值;

    jinfo -syspros pid //用于輸出虛擬機進程的System.getProperties()的內(nèi)容驯击。

    [qianfg@Centos7 ~]$ jinfo -flag InitialHeapSize 22783
    -XX:InitialHeapSize=62914560
    
  • jmap

    jmap是Memory Map for Java的簡稱,用于生成堆轉(zhuǎn)儲快照文件耐亏、查詢finalize執(zhí)行隊列徊都、Java堆和永久代的詳細信息,需要配合具體的選項參數(shù)使用广辰。

    [qianfg@Centos7 ~]$ jmap -heap 22783
    Attaching to process ID 22783, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.221-b11
    
    using thread-local object allocation.
    Parallel GC with 2 thread(s)
    
    Heap Configuration:
       MinHeapFreeRatio         = 0
       MaxHeapFreeRatio         = 100
       MaxHeapSize              = 994050048 (948.0MB)
       NewSize                  = 20971520 (20.0MB)
       MaxNewSize               = 331350016 (316.0MB)
       OldSize                  = 41943040 (40.0MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 21807104 (20.796875MB)
       CompressedClassSpaceSize = 1073741824 (1024.0MB)
       MaxMetaspaceSize         = 17592186044415 MB
       G1HeapRegionSize         = 0 (0.0MB)
    
    Heap Usage:
    PS Young Generation
    Eden Space:
       capacity = 18350080 (17.5MB)
       used     = 14596944 (13.920730590820312MB)
       free     = 3753136 (3.5792694091796875MB)
       79.54703194754464% used
    From Space:
       capacity = 1572864 (1.5MB)
       used     = 131072 (0.125MB)
       free     = 1441792 (1.375MB)
       8.333333333333334% used
    To Space:
       capacity = 1572864 (1.5MB)
       used     = 0 (0.0MB)
       free     = 1572864 (1.5MB)
       0.0% used
    PS Old Generation
       capacity = 29884416 (28.5MB)
       used     = 19405328 (18.506362915039062MB)
       free     = 10479088 (9.993637084960938MB)
       64.93460671943531% used
    
    16678 interned Strings occupying 1501192 bytes.
    
  • jstack

    jstack是Stack Trace for Java的簡稱暇矫,用于顯示當前虛擬機內(nèi)每一條線程正在執(zhí)行的方法堆棧集合,可用于分析線程長時間卡頓的原因轨域。

    [qianfg@Centos7 ~]$ jstack 22783
    2020-03-12 02:48:06
    Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.221-b11 mixed mode):
    
    "Attach Listener" #51 daemon prio=9 os_prio=0 tid=0x00007ff7fc007000 nid=0x1bbe waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "http-nio-8080-exec-15" #50 daemon prio=5 os_prio=0 tid=0x00007ff808026000 nid=0x3c29 waiting on condition [0x00007ff7f01c1000]
       java.lang.Thread.State: WAITING (parking)
    ...此處多行省略
    "VM Thread" os_prio=0 tid=0x00007ff824074000 nid=0x5903 runnable
    
    "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007ff82401f800 nid=0x5901 runnable
    
    "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007ff824021000 nid=0x5902 runnable
    
    "VM Periodic Task Thread" os_prio=0 tid=0x00007ff8240c5800 nid=0x590a waiting on condition
    
    JNI global references: 212
    
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袱耽,一起剝皮案震驚了整個濱河市杀餐,隨后出現(xiàn)的幾起案子干发,更是在濱河造成了極大的恐慌,老刑警劉巖史翘,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枉长,死亡現(xiàn)場離奇詭異,居然都是意外死亡琼讽,警方通過查閱死者的電腦和手機必峰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钻蹬,“玉大人吼蚁,你說我怎么就攤上這事。” “怎么了肝匆?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵粒蜈,是天一觀的道長。 經(jīng)常有香客問我旗国,道長枯怖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任能曾,我火速辦了婚禮度硝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寿冕。我一直安慰自己蕊程,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布驼唱。 她就那樣靜靜地躺著存捺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪曙蒸。 梳的紋絲不亂的頭發(fā)上捌治,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機與錄音纽窟,去河邊找鬼肖油。 笑死,一個胖子當著我的面吹牛臂港,可吹牛的內(nèi)容都是我干的森枪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼审孽,長吁一口氣:“原來是場噩夢啊……” “哼县袱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佑力,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤式散,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后打颤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暴拄,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年编饺,在試婚紗的時候發(fā)現(xiàn)自己被綠了乖篷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡透且,死狀恐怖撕蔼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤鲸沮,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布畅形,位于F島的核電站,受9級特大地震影響诉探,放射性物質(zhì)發(fā)生泄漏日熬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一肾胯、第九天 我趴在偏房一處隱蔽的房頂上張望竖席。 院中可真熱鬧,春花似錦敬肚、人聲如沸毕荐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽憎亚。三九已至,卻和暖如春弄慰,著一層夾襖步出監(jiān)牢的瞬間第美,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工陆爽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留什往,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓慌闭,卻偏偏與公主長得像别威,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子驴剔,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

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

  • 轉(zhuǎn)載blog.csdn.net/ning109314/article/details/10411495/ JVM工...
    forever_smile閱讀 5,366評論 1 56
  • JVM架構(gòu) 當一個程序啟動之前省古,它的class會被類裝載器裝入方法區(qū)(Permanent區(qū)),執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評論 0 7
  • 第二部分 自動內(nèi)存管理機制 第二章 java內(nèi)存異常與內(nèi)存溢出異常 運行數(shù)據(jù)區(qū)域 程序計數(shù)器:當前線程所執(zhí)行的字節(jié)...
    小明oh閱讀 1,159評論 0 2
  • 介紹JVM中7個區(qū)域丧失,然后把每個區(qū)域可能造成內(nèi)存的溢出的情況說明 程序計數(shù)器:看做當前線程所執(zhí)行的字節(jié)碼行號指示器...
    jemmm閱讀 2,229評論 0 9
  • 作者:一字馬胡 轉(zhuǎn)載標志 【2017-11-12】 更新日志 日期更新內(nèi)容備注 2017-11-12新建文章初版 ...
    beneke閱讀 2,202評論 0 7