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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【狂神说】JVM

發(fā)布時(shí)間:2023/12/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【狂神说】JVM 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 1.JVM的位置
    • 2.JVM的體系結(jié)構(gòu)
    • 3.類加載器
    • 4.雙親委派機(jī)制(重要)
    • 5.沙箱安全機(jī)制(了解)
    • 6.native(核心)
    • 7.PC寄存器(了解)
    • 8.方法區(qū)
    • 9.棧
    • 10.三種JVM
    • 11.堆(Heap)
    • 12.新生區(qū)、老年區(qū)
    • 13.永久區(qū)
    • 14.堆內(nèi)存調(diào)優(yōu)
    • 15.GC以及常用算法
        • 引用計(jì)數(shù)法:
        • 復(fù)制算法:
        • 標(biāo)記清除算法:
        • 標(biāo)記壓縮算法:
    • 16.JMM
        • 1、什么是JMM?
        • 2、它干嘛的?
        • 3、它該如何學(xué)習(xí)?
    • 17.總結(jié)

常見的面試題:

  • 請(qǐng)談一談你對(duì)JVM的理解?Java8虛擬機(jī)和之前的變化?
  • 什么是OOM,什么是棧溢出?
  • JVM的常用調(diào)優(yōu)參數(shù)有哪些
  • 內(nèi)存快照如何抓取,怎么分析Dump文件?
  • 談?wù)凧VM中你認(rèn)識(shí)的類加載器

1.JVM的位置

類加載子系統(tǒng):加載、鏈接、初始化

第三方插件:執(zhí)行引擎處

Class File–javac

2.JVM的體系結(jié)構(gòu)

Java棧、本地方法棧、程序計(jì)數(shù)器不會(huì)有垃圾回收,否則程序會(huì)死掉
百分之99的JVM調(diào)優(yōu)都是在方法區(qū)和堆(99%是堆)中調(diào)優(yōu),Java棧、本地方法棧、程序計(jì)數(shù)器是不會(huì)有垃圾存在的。

3.類加載器

作用:加載class文件 new Student();

(有一個(gè)student的類,這個(gè)類是抽象的,當(dāng)使用new關(guān)鍵詞new完后變成具體的實(shí)例,具體的實(shí)例在Java在棧中引用,具體的人實(shí)例放在堆中,要去堆中進(jìn)行真正的數(shù)據(jù)引用)

類是模板,是抽象的,類實(shí)例化得到的對(duì)象是具體的。所有的對(duì)象反射回去得到的是同一個(gè)類模板。

  • 虛擬機(jī)自帶的加載器
  • 啟動(dòng)類(根)加載器 BootstrapClassLoader(rt.jar):主要負(fù)責(zé)加載核心的類庫(kù)(java.lang.*等),構(gòu)造ExtClassLoader和APPClassLoader。
  • 擴(kuò)展類加載器 ?ExtClassLoader(\jre\lib\ext):主要負(fù)責(zé)加載jre/lib/ext目錄下的一些擴(kuò)展的jar。
  • 應(yīng)用程序加載器 ?AppClassLoader(當(dāng)前應(yīng)用程序加載器):主要負(fù)責(zé)加載應(yīng)用程序的主函數(shù)類
  • 百度:雙親委派機(jī)制
  • 4.雙親委派機(jī)制(重要)

    工作原理:

    (1)如果一個(gè)類加載器收到了類加載請(qǐng)求,它并不會(huì)自己先加載,而是把這個(gè)請(qǐng)求委托給父類的加載器去執(zhí)行

    (2)如果父類加載器還存在其父類加載器,則進(jìn)一步向上委托,依次遞歸,請(qǐng)求最終將到達(dá)頂層的引導(dǎo)類加載器;

    (3)如果父類加載器可以完成類加載任務(wù),就成功返回,倘若父類加載器無(wú)法完成加載任務(wù),子加載器才會(huì)嘗試自己去加載,這就是雙親委派機(jī)制

    (4)父類加載器一層一層往下分配任務(wù),如果子類加載器能加載,則加載此類,如果將加載任務(wù)分配至系統(tǒng)類加載器也無(wú)法加載此類,則拋出異常

    當(dāng)一個(gè)Hello.class這樣的文件要被加載時(shí)。不考慮我們自定義類加載器,

    首先會(huì)在AppClassLoader中檢查是否加載過,如果有那就無(wú)需再加載了。

    如果沒有,那么會(huì)拿到父加載器,然后調(diào)用父加載器的loadClass方法。

    父類中同理也會(huì)先檢查自己是否已經(jīng)加載過,如果沒有再往上。

    注意這個(gè)類似遞歸的過程,直到到達(dá)Bootstrap classLoader之前,都是在檢查是否加載過,并不會(huì)選擇自己去加載。直到BootstrapClassLoader,已經(jīng)沒有父加載器了,這時(shí)候開始考慮自己是否能加載了,如果自己無(wú)法加載,會(huì)下沉到子加載器去加載,一直到最底層,如果沒有任何加載器能加載,就會(huì)拋出ClassNotFoundException。那么有人就有下面這種疑問了?

    為什么要設(shè)計(jì)這種機(jī)制?

    這種設(shè)計(jì)有個(gè)好處是,如果有人想替換系統(tǒng)級(jí)別的類:String.java。篡改它的實(shí)現(xiàn),在這種機(jī)制下這些系統(tǒng)的類已經(jīng)被Bootstrap classLoader加載過了(為什么?因?yàn)楫?dāng)一個(gè)類需要加載的時(shí)候,最先去嘗試加載的就是BootstrapClassLoader),所以其他類加載器并沒有機(jī)會(huì)再去加載,從一定程度上防止了危險(xiǎn)代碼的植入。


    舉例一、

    我自己建立一個(gè) java.lang.String 類,寫上 static 代碼塊

    package java.lang;public class String {static{System.out.println("我是自定義的String類的靜態(tài)代碼塊");} }

    在另外的程序中加載 String 類,看看加載的 String 類是 JDK 自帶的 String 類,還是我們自己編寫的 String 類

    public class StringTest {public static void main(String[] args) {java.lang.String str = new java.lang.String();System.out.println("hello,atguigu.com");StringTest test = new StringTest();System.out.println(test.getClass().getClassLoader());} }

    為什么呢?
    由于我們定義的String類本應(yīng)用系統(tǒng)類加載器,但它并不會(huì)自己先加載,而是把這個(gè)請(qǐng)求委托給父類的加載器去執(zhí)行,到了擴(kuò)展類加載器發(fā)現(xiàn)String類不歸自己管,再委托給父類加載器(引導(dǎo)類加載器),這時(shí)發(fā)現(xiàn)是java.lang包,這事就歸引導(dǎo)類加載器管,所以加載的是 JDK 自帶的 String 類


    舉例二、

    在我們自己的 String 類中整個(gè) main() 方法

    package java.lang;public class String {static{System.out.println("我是自定義的String類的靜態(tài)代碼塊");}//錯(cuò)誤: 在類 java.lang.String 中找不到 main 方法public static void main(String[] args) {System.out.println("hello,String");} }

    由于雙親委派機(jī)制找到的是 JDK 自帶的 String 類,但在引導(dǎo)類加載器的核心類庫(kù)API里的 String 類中并沒有 main() 方法


    舉例三、

    舉例 3:
    在 java.lang 包下整個(gè) ShkStart 類 (自定義類名)

    package java.lang;public class ShkStart {public static void main(String[] args) {System.out.println("hello!");} }

    出于保護(hù)機(jī)制,java.lang 包下不允許我們自定義類

    雙親委派機(jī)制優(yōu)勢(shì)

    通過上面的例子,我們可以知道,雙親機(jī)制可以

    • 避免類的重復(fù)加載
    • 保護(hù)程序安全,防止核心API被隨意篡改
      • 自定義類:java.lang.String (沒用)
      • 自定義類:java.lang.ShkStart(報(bào)錯(cuò):阻止創(chuàng)建 java.lang開頭的類)
  • Class Not Found異常就是這么來(lái)的
  • Null:Java調(diào)用不到。(底層是C、C++寫的)Java早期的名字:C+±- ?Java = C+±-:去掉繁瑣的東西,指針,內(nèi)存管理~
  • Java語(yǔ)言保留了C的接口,這些方法就是用native(本地)修飾的,java通過native方法調(diào)用操作系統(tǒng)的方法
  • 5.沙箱安全機(jī)制(了解)

    Java安全模型的核心就是Java沙箱(sanddiox),什么是沙箱?沙箱是一個(gè)限制程序運(yùn)行的環(huán)境。沙箱機(jī)制就是將Java代碼限定在虛擬機(jī) (JVM) 特定的運(yùn)行范圍中,并且嚴(yán)格限制代碼對(duì)本地系統(tǒng)資源訪問,通過這樣的措施來(lái)保證對(duì)代碼的有效隔離,防止對(duì)本地系統(tǒng)造成破壞。沙箱主要限制系統(tǒng)資源訪問,那系統(tǒng)資源包括什么? CPU、內(nèi)存、文件系統(tǒng)、網(wǎng)絡(luò)。不同級(jí)別的沙箱對(duì)這些資源訪問的限制也可以不一樣。

    所有的Java程序運(yùn)行都可以指定沙箱,可以定制安全策略。

    在Java中將執(zhí)行程序分成本地代碼和遠(yuǎn)程代碼兩種,本地代碼默認(rèn)視為可信任的,而遠(yuǎn)程代碼則被看作是不受信的。對(duì)于授信的本地代碼,可以訪問一切本地資源。而對(duì)于非授信的遠(yuǎn)程代碼在早期的Java實(shí)現(xiàn)中,安全依賴于沙箱(Sandbox)機(jī)制。如下圖所示JDK1.0安全模型

    但如此嚴(yán)格的安全機(jī)制也給程序的功能擴(kuò)展帶來(lái)障礙,比如當(dāng)用戶希望遠(yuǎn)程代碼訪問本地系統(tǒng)的文件時(shí)候,就無(wú)法實(shí)現(xiàn)。因此在后續(xù)的Java1.1版本中,針對(duì)安全機(jī)制做了改進(jìn),增加了安全策略,允許用戶指定代碼對(duì)本地資源的訪問權(quán)限。如下圖所示JDK1.1安全模型

    在Java1.2版本中,再次改進(jìn)了安全機(jī)制,增加了代碼簽名。不論本地代碼或是遠(yuǎn)程代碼,都會(huì)按照用戶的安全策略設(shè)定,由類加載器加載到虛擬機(jī)中權(quán)限不同的運(yùn)行空間,來(lái)實(shí)現(xiàn)差異化的代碼執(zhí)行權(quán)限控制。如下圖所示

    當(dāng)前最新的安全機(jī)制實(shí)現(xiàn),則引入了**域(Domain)**的概念。虛擬機(jī)會(huì)把所有代碼加載到不同的系統(tǒng)域和應(yīng)用域,系統(tǒng)域部分專門負(fù)責(zé)與關(guān)鍵資源進(jìn)行交互,而各個(gè)應(yīng)用域部分則通過系統(tǒng)域的部分代理來(lái)對(duì)各種需要的資源進(jìn)行訪問。虛擬機(jī)中不同的受保護(hù)域(Protected Domain),對(duì)應(yīng)不一樣的權(quán)限(Permission)。存在于不同域中的類文件就具有了當(dāng)前域的全部權(quán)限,如下圖所示最新的安全模型(jdk 1.6)

    組成沙箱的基本組件

    字節(jié)碼校驗(yàn)器(bytecode verifier):確保Java類文件遵循Java語(yǔ)言規(guī)范。這樣可以幫助Java程序?qū)崿F(xiàn)內(nèi)存保護(hù)。但并不是所有的類文件都會(huì)經(jīng)過字節(jié)碼校驗(yàn),比如核心類。

    類裝載器(class loader) :其中類裝載器在3個(gè)方面對(duì)Java沙箱起作用

    它防止惡意代碼去干涉善意的代碼; //雙親委派機(jī)制

    它守護(hù)了被信任的類庫(kù)邊界;

    它將代碼歸入保護(hù)域,確定了代碼可以進(jìn)行哪些操作。

    虛擬機(jī)為不同的類加載器載入的類提供不同的命名空間,命名空間由一系列唯一的名稱組成, 每一個(gè)被裝載的類將有一個(gè)名字,這個(gè)命名空間是由Java虛擬機(jī)為每一個(gè)類裝載器維護(hù)的,它們互相之間甚至不可見。 ?
    類裝載器采用的機(jī)制是雙親委派模式。

    從最內(nèi)層JVM自帶類加載器開始加載,外層惡意同名類得不到加載從而無(wú)法使用;

    由于嚴(yán)格通過包來(lái)區(qū)分了訪問域,外層惡意的類通過內(nèi)置代碼也無(wú)法獲得權(quán)限訪問到內(nèi)層類,破壞代碼就自然無(wú)法生效。
    ●存取控制器(access controller) :存取控制器可以控制核心API對(duì)操作系統(tǒng)的存取權(quán)限,而這個(gè)控制的策略設(shè)定,可以由用戶指定。
    ●安全管理器(security manager) : 是核心API和操作系統(tǒng)之間的主要接口。實(shí)現(xiàn)權(quán)限控制,比存取控制器優(yōu)先級(jí)高。
    ●安全軟件包(security package) : java.security下的類和擴(kuò)展包下的類,允許用戶為自己的應(yīng)用增加新的安全特性,包括:

    安全提供者

    消息摘要

    數(shù)字簽名 keytools https

    加密

    鑒別

    6.native(核心)

    native:

    凡是帶了native關(guān)鍵字的,說明java的作用范圍達(dá)不到了,會(huì)去調(diào)用底層c語(yǔ)言的庫(kù)

    會(huì)進(jìn)入本地方法棧

    調(diào)用本地方法本地接口 JNI (Java Native Interface)

    JNI作用:開拓Java的使用,融合不同的編程語(yǔ)言為Java所用,最初: C、C++

    Java誕生的時(shí)候C、C++橫行,想要立足,必須要有調(diào)用C、C++的程序

    它在內(nèi)存區(qū)域中專門開辟了一塊標(biāo)記區(qū)域: Native Method Stack,登記native方法

    在最終執(zhí)行的時(shí)候,加載本地方法庫(kù)中的方法通過JNI

    例如:Java程序驅(qū)動(dòng)打印機(jī),管理系統(tǒng),掌握即可,在企業(yè)級(jí)應(yīng)用比較少
    private native void start0();

    調(diào)用其他接口:Socket… WebService … http~

    ? 目前該方法使用的越來(lái)越少了,除非是與硬件有關(guān)的應(yīng)用,比如通過Java程序驅(qū)動(dòng)打印機(jī)或者Java系統(tǒng)管理設(shè)備,在企業(yè)級(jí)應(yīng)用中已經(jīng)比較少見。因?yàn)楝F(xiàn)在的異構(gòu)領(lǐng)域間通信很發(fā)達(dá),比如可以使用Socket通信,也可以使用Web Service等等,不多做介紹!

    Native Method Stack

    它的具體做法是Native Method Stack 中登記native方法,在 ( Execution Engine ) 執(zhí)行引擎執(zhí)行的時(shí)候加載Native Libraies?!颈镜貛?kù)】

    7.PC寄存器(了解)

    程序計(jì)數(shù)器: Program Counter Register ?
    ?每個(gè)線程都有一個(gè)程序計(jì)數(shù)器,是線程私有的,就是一個(gè)指針, 指向方法區(qū)中的方法字節(jié)碼(用來(lái)存儲(chǔ)指向像一條指令的地址, 也即將要執(zhí)行的指令代碼),在執(zhí)行引擎讀取下一條指令, 是一個(gè)非常小的內(nèi)存空間,幾乎可以忽略不計(jì)

    8.方法區(qū)

    方法區(qū):Method Area

    ? 方法區(qū)是被所有線程共享,所有字段和方法字節(jié)碼,以及一些特殊方法,如構(gòu)造函數(shù),接口代碼也在此定義,簡(jiǎn)單說,所有定義的方法的信息都保存在該區(qū)域,此區(qū)域?qū)儆诠蚕韰^(qū)間;

    靜態(tài)變量、常量、類信息(構(gòu)造方法、接口定義)、運(yùn)行時(shí)的常量池存在方法區(qū)中,但是實(shí)例變量存在堆內(nèi)存中,和方法區(qū)無(wú)關(guān)

    static、final、Class、常量池

    9.棧

    1、棧:數(shù)據(jù)結(jié)構(gòu)(棧跟隊(duì)列比較學(xué)習(xí))

    程序 = 數(shù)據(jù)結(jié)構(gòu)+算法︰持續(xù)學(xué)習(xí)~

    程序 = 框架+業(yè)務(wù)邏輯︰吃飯~(被淘汰)(springboot+springcloud)

    棧:先進(jìn)后出、后進(jìn)先出,類似一個(gè)桶()

    隊(duì)列:先進(jìn)先出( FIFO : First Input First Output )

    為什么main()先執(zhí)行,最后結(jié)束~(main()方法先壓入棧,再壓入其他方法,main()最后彈出)

    棧溢出:StackOverflowError

    public void test(){a(); } public void a(){test(); }

    棧:也叫棧內(nèi)存

    主管程序的運(yùn)行,生命周期和線程同步;

    線程結(jié)束,棧內(nèi)存也就釋放,對(duì)于棧來(lái)說,==不存在垃圾回收的問題;==一旦線程結(jié)束,棧就Over;

    棧:棧內(nèi)存中放8大基本類型+對(duì)象引用+實(shí)例的方法

    棧運(yùn)行原理:棧幀

    棧幀:局部變量表+操作數(shù)棧

    每執(zhí)行一個(gè)方法,就會(huì)產(chǎn)生一個(gè)棧幀。程序正在運(yùn)行的方法永遠(yuǎn)都會(huì)在棧的頂部

    棧+堆+方法區(qū)的交互關(guān)系:

    查的內(nèi)容:棧具體怎么存

    手動(dòng)畫出一個(gè)對(duì)象實(shí)例化的過程在內(nèi)存中(百度、視頻)

    調(diào)優(yōu)是在堆中調(diào)優(yōu),堆是比較重要的

    10.三種JVM

    java -version

    • Sun: HotSpot (java Hotspot?64-Bit server vw (build 25.181-b13,mixed mode))
    • BEA :JRockit
    • IBM: j9VM
    • 我們學(xué)習(xí)都是:Hotspot

    11.堆(Heap)

    一個(gè)JVM只有一個(gè)堆內(nèi)存,堆內(nèi)存的大小是可以調(diào)節(jié)的。

    類加載器讀取了類文件后,一般會(huì)把什么東西放到堆中?

    類,方法,常量,變量~,保存我們所有引用類型的真實(shí)對(duì)象

    堆內(nèi)存中還要細(xì)分為三個(gè)區(qū)域:

    • 新生區(qū)(伊甸園區(qū)) Young/New
    • 養(yǎng)老區(qū) Old
    • 永久區(qū) Perm

    GC:Garbage recycling

    • 輕GC:輕量級(jí)垃圾回收,主要是在新生區(qū)
    • 重GC(Full GC):重量級(jí)垃圾回收,主要是養(yǎng)老區(qū),重GC就說明內(nèi)存都要爆了

    GC垃圾回收,主要是在伊甸園區(qū)和養(yǎng)老區(qū)~

    假設(shè)內(nèi)存滿了,OOM(Out Of memory),堆內(nèi)存不夠!

    java.lang.OutOfMemoryError: Java heap space

    在JDK8以后,永久存儲(chǔ)區(qū)改了個(gè)名字(元空間);

    12.新生區(qū)、老年區(qū)

    新生區(qū):

    類誕生和成長(zhǎng)的地方,甚至死亡

    • 伊甸園區(qū):所有的對(duì)象都是在伊甸園區(qū)new出來(lái)的
    • 幸存(0區(qū),1區(qū))

    真理:經(jīng)過研究,99%的對(duì)象都是臨時(shí)對(duì)象!

    13.永久區(qū)

    這個(gè)區(qū)域常駐內(nèi)存的,用來(lái)存放jdk自身攜帶的class對(duì)象,interface元數(shù)據(jù)

    存儲(chǔ)的是Java運(yùn)行時(shí)的一些環(huán)境或類信息

    這個(gè)區(qū)域不存在垃圾回收

    關(guān)閉虛擬機(jī)就會(huì)釋放這個(gè)區(qū)域的內(nèi)存

    一個(gè)啟動(dòng)類,加載了大量的第三方j(luò)ar包,、tomcat部署了太多應(yīng)用,大量動(dòng)態(tài)生成的反射類。不斷地被加載直到內(nèi)存滿,就會(huì)出現(xiàn)OOM;

    • jdk1.6以前:永久代,常量池在方法區(qū)
    • jdk1.7:永久代,但是慢慢退化了,去永久代,常量池在堆中
    • jdk1.8:無(wú)永久區(qū),常量池在元空間

    堆:新生區(qū)+老年區(qū)

    元空間:非堆(邏輯上存在,物理上不存在)

    OOM:

    在一個(gè)項(xiàng)目中突然出現(xiàn)了OOM故障,那么如何排除,研究為什么錯(cuò)

    • 能夠看到代碼第幾行出錯(cuò):內(nèi)存快照分析工具
    • Debug:一行行分析代碼

    MAT、Jprofiler的作用:

    • 分析Dump內(nèi)存文件,快速定位內(nèi)存泄漏;
    • 獲得堆中的數(shù)據(jù)
    • 獲得大的對(duì)象

    14.堆內(nèi)存調(diào)優(yōu)

    Settings–Plugins–JProfiler

    JProfiler客戶端官網(wǎng)下載

    -Xm:設(shè)置初始化內(nèi)存分配大小,默認(rèn)1/64

    -Xmx:設(shè)置最大分配內(nèi)存,默認(rèn) 1/4

    -XX:+PrintGCDetails (打印GC垃圾回收信息)

    -XX:+HeapDumpOutOfMenoryError(oom Dump)

    ?

    biggest object–Thread Dump–main

    15.GC以及常用算法

    JVM在進(jìn)行GC時(shí),并不是對(duì)堆中這三個(gè)區(qū)域統(tǒng)一回收,大部分時(shí)候回收都是新生代

    GC:垃圾分代收集算法

    • 輕GC:
    • 重GC:全局GC

    GC題目:

    • JVM的內(nèi)存模型和分區(qū),詳細(xì)到每個(gè)區(qū)放什么?
    • 堆里面的分區(qū)有哪些?Eden、from、to、老年區(qū)、說說他們的特點(diǎn)
    • GC算法有哪些?標(biāo)記清除法、標(biāo)記壓縮、復(fù)制算法,引用計(jì)數(shù)器(比較少)怎么用?
    • 輕GC和重GC分別在什么時(shí)候發(fā)生?

    引用計(jì)數(shù)法:

    JVM一般不會(huì)采用這種方式,不高效,計(jì)數(shù)器繁瑣,一個(gè)大項(xiàng)目有很多對(duì)象

    復(fù)制算法:

    • 好處:沒有內(nèi)存的碎片
    • 壞處:浪費(fèi)了內(nèi)存空間,多了一半空間永遠(yuǎn)是空的(浪費(fèi)一個(gè)幸存區(qū))
    • 極端情況下:
      • 假設(shè)對(duì)象100%存活,把所有拷貝到幸存區(qū),所有地址重新做一遍
      • 假設(shè)from區(qū)是滿的,全部復(fù)制到to區(qū),成本很高。
    • 復(fù)制算法最佳使用場(chǎng)景:對(duì)象存活度較低的時(shí)候(新生區(qū))

    標(biāo)記清除算法:

    缺點(diǎn):兩次掃描,嚴(yán)重浪費(fèi)時(shí)間,會(huì)產(chǎn)生內(nèi)存碎片

    優(yōu)點(diǎn):不需要額外的空間

    標(biāo)記壓縮算法:

    優(yōu)點(diǎn):再次掃描,向一端移動(dòng)存活的對(duì)象,防止內(nèi)存碎片產(chǎn)生

    缺點(diǎn):又多了一次掃描成本

    總結(jié)

    • 內(nèi)存效率:復(fù)制算法>標(biāo)記清除算法>標(biāo)記壓縮算法(時(shí)間復(fù)雜度)
    • 內(nèi)存整齊度:復(fù)制算法=標(biāo)記壓縮算法>標(biāo)記清除算法
    • 內(nèi)存利用率:標(biāo)記壓縮算法=標(biāo)記清除算法>復(fù)制算法

    思考一個(gè)問題:難道沒有最優(yōu)算法嗎?

    答案:沒有,沒有最好的算法,只有最合適的算法 —>( GC:分代收集算法)

    • 分代收集算法:
      • 年輕代:存活率低(復(fù)制算法)!
      • 老年代:區(qū)域大,存活率高(標(biāo)記清除 (內(nèi)存碎片不是太多) + 標(biāo)記壓縮混合實(shí)現(xiàn)

    一天時(shí)間學(xué)JVM,不現(xiàn)實(shí),要深究,必須要下去花時(shí)間,和多看面試題,以及《深入理解JVM》

    但是,我們可以掌握一個(gè)學(xué)習(xí)JVM的方法~

    16.JMM

    1、什么是JMM?

    JMM:(Java Memory Model的縮寫):Java內(nèi)存模型【百度百科】

    2、它干嘛的?

    官方,其他人的博客,對(duì)應(yīng)的視頻!

    作用:緩存一致性協(xié)議,用于定義數(shù)據(jù)讀寫的規(guī)則 (遵守,找到這個(gè)規(guī)則)。

    JMM定義了線程工作內(nèi)存和主內(nèi)存之間的抽象關(guān)系:線程之間的共享變量存儲(chǔ)在主內(nèi)存(Main Memory)中,每個(gè)線程都有一個(gè)私有的本地內(nèi)存(Local Memory),是從主內(nèi)中拷貝的。

    解決共享對(duì)象可見性這個(gè)問題: volilate;一旦刷新了就會(huì)很快的同步到主內(nèi)存中。

    3、它該如何學(xué)習(xí)?

    JMM:抽象的概念,理論

    JMM對(duì)這八種指令的使用,制定了如下規(guī)則:

    • 不允許read和load、store和write操作之一單獨(dú)出現(xiàn)。即使用了read必須load,使用了store必須write;

    • 不允許線程丟棄他最近的assign操作,即工作變量的數(shù)據(jù)改變了之后,必須告知主存;

    • 不允許一個(gè)線程將沒有assign的數(shù)據(jù)從工作內(nèi)存同步回主內(nèi)存;

    • 一個(gè)新的變量必須在主內(nèi)存中誕生,不允許工作內(nèi)存直接使用一個(gè)未被初始化的變量。就是對(duì)變量實(shí)施use、store操作之前,必須經(jīng)過assign和load操作;

    • 一個(gè)變量同一時(shí)間只有一個(gè)線程能對(duì)其進(jìn)行l(wèi)ock。多次lock后,必須執(zhí)行相同次數(shù)的unlock才能解鎖;

    • 如果對(duì)一個(gè)變量進(jìn)行l(wèi)ock操作,會(huì)清空所有工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個(gè)變量前,必須重新load或assign操作初始化變量的值;

    • 如果一個(gè)變量沒有被lock,就不能對(duì)其進(jìn)行unlock操作。也不能unlock一個(gè)被其他線程鎖住的變量;

    • 對(duì)一個(gè)變量進(jìn)行unlock操作之前,必須把此變量同步回主內(nèi)存

    JMM對(duì)這八種操作規(guī)則和對(duì)volatile的一些特殊規(guī)則就能確定哪里操作是線程安全,哪些操作是線程不安全的了。但是這些規(guī)則實(shí)在復(fù)雜,很難在實(shí)踐中直接分析。所以一般我們也不會(huì)通過上述規(guī)則進(jìn)行分析。更多的時(shí)候,使用java的happen-before規(guī)則來(lái)進(jìn)行分析。

    搜索:JMM面試題

    17.總結(jié)

    學(xué)習(xí)新東西是常態(tài):

    • 如何針對(duì)面試學(xué)習(xí)。
    • 如何針對(duì)技術(shù)學(xué)習(xí)。

    針對(duì)面試學(xué)習(xí):3/10–pass,總結(jié)面經(jīng),分析這10,再觸類旁通一下:百度面試題

    通過大量的面試總結(jié),得出一套解題思路;

    學(xué)習(xí)方式:在線畫圖網(wǎng)站推薦搜索

    https://www.processon.com/popular?criterion=jvm

    百度:JVM參數(shù)(調(diào)優(yōu))+jvm內(nèi)存的年輕代/老年代/持久代

    總結(jié)

    以上是生活随笔為你收集整理的【狂神说】JVM的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。