日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试必会系列 - 1.7 JVM 内存模型

發布時間:2024/2/28 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试必会系列 - 1.7 JVM 内存模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文已收錄至 Github(MD-Notes),若博客中圖片模糊或打不開,可以來我的 Github 倉庫,包含了完整圖文:https://github.com/HanquanHq/MD-Notes,涵蓋了互聯網大廠面試必問的知識點,講解透徹,長期更新中,歡迎一起學習探討 ~

更多內容,可以訪問:

面試必會系列專欄:https://blog.csdn.net/sinat_42483341/category_10300357.html
操作系統系列專欄:https://blog.csdn.net/sinat_42483341/category_10519484.html


JVM

查看 JVM 啟動默認參數:java -XX:+PrintCommandLineFlags -version

java -XX:+PrintCommandLineFlags -version -XX:InitialHeapSize=266536512 -XX:MaxHeapSize=4264584192 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC java version "1.8.0_251" Java(TM) SE Runtime Environment (build 1.8.0_251-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.251-b08, mixed mode)

對象內存布局

new Object() 對象在內存中占多少字節?16字節

8 字節(MarkWord,固定大小)

4 字節(開啟壓縮時的對象指針 ClassPointer,指向你的對象 TT.class)

0 字節 Instance data,要看你的對象有多少成員變量

4 字節 padding(對齊,要被 8 整除)

查看對象的內存布局工具:JOL = Java Object Layout

<dependencies><!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core --><dependency><groupId>org.openjdk.jol</groupId><artifactId>jol-core</artifactId><version>0.9</version></dependency> </dependencies> public class MyTest {public static void main(String[] args) {Object o = new Object(); // 不加鎖o.hashCode();System.out.println(ClassLayout.parseInstance(o).toPrintable());Object o1 = new Object();synchronized (o1) { // 加鎖System.out.println(ClassLayout.parseInstance(o1).toPrintable());}} }

1、不加鎖時,對象內存布局如下:

(注意,jdk 11 需要指定 -XX:-UseBiasedLocking 參數,取消偏向鎖) 001 表示沒有鎖

2、添加 syncronized 之后,如下。下面 00 表示輕量級鎖,因為偏向鎖未啟動,直接升級為了輕量級鎖

3、添加參數,啟動偏向鎖:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0

對象頭包括什么?JDK 1.8 的實現如下

對象頭包括: MarkWord,classpointer,Instance data,padding

**MarkWord 包括:**鎖信息、HashCode、GC信息

在 hotspot 源碼 jdk8u: markOop.hpp 中,詳細的說明了 object header 的布局。理解即可,無需背過。

The markOop describes the header of an object. Bit-format of an object header (most significant first, big endian layout below):32 bits: -------- hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object) JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object) size:32 ------------------------------------------>| (CMS free block) PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)64 bits: -------- unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object) JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object) PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object) size:64 ----------------------------------------------------->| (CMS free block)unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object) JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object) narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->|(COOPs&&CMSpromotedobject) unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

總結 JDK8 中對象的 object header 布局如下(64 位,也就是 8 字節):

要看加的是什么鎖的話,先看 markword 的最低兩位,是 01 / 00 / 10 / 11

64位 markword 構成

為什么 GC 年齡默認為 15?因為分代年齡只有 4 bit,可以表示最大的數就是 15

對象分配過程?

見《Java垃圾回收機制.md》- 對象分配過程

對象怎么定位?

怎么通過 t 找到 new T()?

  • 通過句柄池(間接法)
  • 通過直接指針,效率高(HotSpot用的是這種方式),缺點是在GC需要移動對象時reference本身需要被修改

Java 程序是怎樣運行的?

1、首先,通過 Javac 編譯器將 .java 轉為 JVM 可加載的 .class 字節碼文件。

Javac 是由 Java 編寫的程序,編譯過程可以分為:

① 詞法解析,通過空格分割出單詞、操作符、控制符等信息,形成 token 信息流,傳遞給語法解析器。

② 語法解析,把 token 信息流按照 Java 語法規則組裝成語法樹。

③ 語義分析,檢查關鍵字使用是否合理、類型是否匹配、作用域是否正確等。

④ 字節碼生成,將前面各個步驟的信息轉換為字節碼。

字節碼必須通過類加載過程加載到 JVM 后才可以執行,執行有三種模式,解釋執行、JIT 編譯執行、JIT 編譯與解釋器混合執行(主流 JVM 默認執行的方式)。混合模式的優勢在于解釋器在啟動時先解釋執行,省去編譯時間。

2、之后,通過即時編譯器 JIT 把字節碼文件編譯成本地機器碼。

Java 程序最初都是通過解釋器進行解釋執行的,當虛擬機發現某個方法或代碼塊的運行特別頻繁,就會認定其為"熱點代碼",虛擬機即時編譯器會把它們編譯成本地機器碼。

3、還可以通過靜態的提前編譯器 AOT 直接把程序編譯成與目標機器指令集相關的二進制代碼。

JVM內存模型

class 的生命周期

  • 靜靜躺在磁盤中的 .class 文件
  • 經過 load,link,initialize,進入 JVM
  • 經過 JVM 的 run engine,進入 JVM 的運行時數據區
  • 最終被 GC
  • Run-time data areas 運行時數據區的組成

    我們常說的:棧放方法,堆存對象

    堆里面存放的都是一些引用,而棧是我們真正用來執行程序的。可以把每一個方法看做對應一個棧幀。

    動態鏈接:把符號引用(.class文件常量池中的引用)轉化為直接引用(指向堆中的對象)

    每個線程有自己獨立的 PC,VMS,NMS

    線程之間共享 Heap 以及 MethodArea

    PC:程序計數器

    MethodArea:方法區

    類的所有字段和方法字節碼,以及一些特殊方法構造函數,接口代碼也在這里定義。簡單來說,所有定義方法的信息都保存在該區域,靜態變量+常量+類信息(構造方法/接口定義)+運行時常量池都存在方法區中

    方法區只是對于虛擬機的規范。所有的虛擬機應該有方法區,不同虛擬機方法區的叫法不一樣

    • jdk 1.8 之前,HotSpot 使用 PermSpace 永久代 實現方法區
      • 字符串常量位于 Perm Space
      • FGC 不會清理
    • jdk 1.8 及之后:使用 Meta Space 元數據區
      • 字符串常量位于 Heap
      • FGC 會清理

    Stacks:棧空間

    • 棧中存放棧幀
      • 局部變量表
      • 操作數棧
      • 動態鏈接
      • 返回值地址

    Heap:堆空間

    虛擬機啟動時自動分配創建,用于存放對象的實例,幾乎所有對象都在堆上分配內存,當對象無法在該空間申請內存時,拋出OOM異常。也是垃圾收集器管理的主要區域。

    • 類實例
    • 為數組分配的空間

    DirectMemory:直接內存

    • JVM可以直接訪問OS管理的內存,提高效率

      • 零拷貝(不需要拷貝),NIO用到

    Run-Time Constant Pool 運行時常量池

    線程私有的:是交由 JVM 自動化管理的。我們做的 JVM 調優,是調的堆和方法區。

    面試題:下面輸出 i 為多少?

    package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet;public class TestIPulsPlus {public static void main(String[] args) {int i = 8;i = i++; // i = ++i;System.out.println(i);} }

    超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

    總結

    以上是生活随笔為你收集整理的面试必会系列 - 1.7 JVM 内存模型的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。