最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于Java虛擬機(jī)HotSpot

 更新時(shí)間:2021年11月03日 14:56:59   作者:鳩摩  
這篇文章主要介紹了關(guān)于Java虛擬機(jī)HotSpot,在Java類中的一些方法會(huì)被由C/C++編寫(xiě)的HotSpot虛擬機(jī)的C/C++函數(shù)調(diào)用,不過(guò)由于Java方法與C/C++函數(shù)的調(diào)用約定不同,所以并不能直接調(diào)用,需要JavaCalls::call()這個(gè)函數(shù)輔助調(diào)用,下面我們來(lái)看看文章對(duì)內(nèi)容的具體介紹

我們寫(xiě)的主類中的main()方法是如何被Java虛擬機(jī)調(diào)用到的?在Java類中的一些方法會(huì)被由C/C++編寫(xiě)的HotSpot虛擬機(jī)的C/C++函數(shù)調(diào)用,不過(guò)由于Java方法與C/C++函數(shù)的調(diào)用約定不同,所以并不能直接調(diào)用,需要JavaCalls::call()這個(gè)函數(shù)輔助調(diào)用。(我把由C/C++編寫(xiě)的叫函數(shù),把Java編寫(xiě)的叫方法,后續(xù)也會(huì)延用這樣的叫法)如下圖所示。

從C/C++函數(shù)中調(diào)用的一些Java方法主要有:

  • (1)Java主類中的main()方法;
  • (2)Java主類裝載時(shí),調(diào)用JavaCalls::call()函數(shù)執(zhí)行checkAndLoadMain()方法;
  • (3)類的初始化過(guò)程中,調(diào)用JavaCalls::call()函數(shù)執(zhí)行的Java類初始化方法<clinit>,可以查看JavaCalls::call_default_constructor()函數(shù),有對(duì)<clinit>方法的調(diào)用邏輯;
  • (4)我們先省略main方法的執(zhí)行流程(其實(shí)main方法的執(zhí)行也是先啟動(dòng)一個(gè)JavaMain線程,套路都是一樣的),單看某個(gè)JavaThread的啟動(dòng)過(guò)程。JavaThread的啟動(dòng)最終都要通過(guò)一個(gè)native方法java.lang.Thread#start0()方法完成的,這個(gè)方法經(jīng)過(guò)解釋器的native_entry入口,調(diào)用到了JVM_StartThread()函數(shù)。其中的static void thread_entry(JavaThread* thread, TRAPS)函數(shù)中會(huì)調(diào)用JavaCalls::call_virtual()函數(shù)。JavaThread最終會(huì)通過(guò)JavaCalls::call_virtual()函數(shù)來(lái)調(diào)用字節(jié)碼中的run()方法;
  • (5)在SystemDictionary::load_instance_class()這個(gè)能體現(xiàn)雙親委派的函數(shù)中,如果類加載器對(duì)象不為空,則會(huì)調(diào)用這個(gè)類加載器的loadClass()函數(shù)(通過(guò)call_virtual()函數(shù)來(lái)調(diào)用)來(lái)加載類。

當(dāng)然還會(huì)有其它方法,這里就不一一列舉了。通過(guò)JavaCalls::call() 、JavaCalls::call_helper()等函數(shù)調(diào)用Java方法,這些函數(shù)定義在JavaCalls類中,

這個(gè)類的定義如下:

從C/C++函數(shù)中調(diào)用的一些Java方法主要有:

  • (1)Java主類中的main()方法;
  • (2)Java主類裝載時(shí),調(diào)用JavaCalls::call()函數(shù)執(zhí)行checkAndLoadMain()方法;
  • (3)類的初始化過(guò)程中,調(diào)用JavaCalls::call()函數(shù)執(zhí)行的Java類初始化方法<clinit>,可以查看JavaCalls::call_default_constructor()函數(shù),有對(duì)<clinit>方法的調(diào)用邏輯;
  • (4)我們先省略main方法的執(zhí)行流程(其實(shí)main方法的執(zhí)行也是先啟動(dòng)一個(gè)JavaMain線程,套路都是一樣的),單看某個(gè)JavaThread的啟動(dòng)過(guò)程。JavaThread的啟動(dòng)最終都要通過(guò)一個(gè)native方法java.lang.Thread#start0()方法完成的,這個(gè)方法經(jīng)過(guò)解釋器的native_entry入口,調(diào)用到了JVM_StartThread()函數(shù)。其中的static void thread_entry(JavaThread* thread, TRAPS)函數(shù)中會(huì)調(diào)用JavaCalls::call_virtual()函數(shù)。JavaThread最終會(huì)通過(guò)JavaCalls::call_virtual()函數(shù)來(lái)調(diào)用字節(jié)碼中的run()方法;
  • (5)在SystemDictionary::load_instance_class()這個(gè)能體現(xiàn)雙親委派的函數(shù)中,如果類加載器對(duì)象不為空,則會(huì)調(diào)用這個(gè)類加載器的loadClass()函數(shù)(通過(guò)call_virtual()函數(shù)來(lái)調(diào)用)來(lái)加載類。

當(dāng)然還會(huì)有其它方法,這里就不一一列舉了。通過(guò)JavaCalls::call()JavaCalls::call_helper()等函數(shù)調(diào)用Java方法,這些函數(shù)定義在JavaCalls類中,

這個(gè)類的定義如下:

源代碼位置:openjdk/hotspot/src/share/vm/runtime/javaCalls.hpp
 
class JavaCalls: AllStatic {
  static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS);
 public:
  
  static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS);
 
  // 使用如下函數(shù)調(diào)用Java中一些特殊的方法,如類初始化方法<clinit>等
  // receiver表示方法的接收者,如A.main()調(diào)用中,A就是方法的接收者
  static void call_special(JavaValue* result, KlassHandle klass, Symbol* name,Symbol* signature, JavaCallArguments* args, TRAPS);
  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass,Symbol* name, Symbol* signature, TRAPS); 
  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass,Symbol* name, Symbol* signature, Handle arg1, TRAPS);
  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass,Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
  // 使用如下函數(shù)調(diào)用動(dòng)態(tài)分派的一些方法
  static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name,Symbol* signature, JavaCallArguments* args, TRAPS);
  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass,Symbol* name, Symbol* signature, TRAPS); 
  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass,Symbol* name, Symbol* signature, Handle arg1, TRAPS);
  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass,Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
  // 使用如下函數(shù)調(diào)用Java靜態(tài)方法
  static void call_static(JavaValue* result, KlassHandle klass,Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);
   static void call_static(JavaValue* result, KlassHandle klass,Symbol* name, Symbol* signature, TRAPS);
  static void call_static(JavaValue* result, KlassHandle klass,Symbol* name, Symbol* signature, Handle arg1, TRAPS);
  static void call_static(JavaValue* result, KlassHandle klass,Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);
 
  // 更低一層的接口,如上的一些函數(shù)可能會(huì)最終調(diào)用到如下這個(gè)函數(shù)
  static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);
};


如上的函數(shù)都是自解釋的,通過(guò)名稱我們就能看出這些函數(shù)的作用。其中JavaCalls::call()函數(shù)是更低一層的通用接口。Java虛擬機(jī)規(guī)范定義的字節(jié)碼指令共有5個(gè),分別為invokestatic invokedynamic 、invokestatic invokespecial、invokevirtual幾種方法調(diào)用指令。這些call_static() call_virtual()函數(shù)內(nèi)部調(diào)用了call()函數(shù)。這一節(jié)我們先不介紹各個(gè)方法的具體實(shí)現(xiàn)。下一篇將詳細(xì)介紹。

我們選一個(gè)重要的main()方法來(lái)查看具體的調(diào)用邏輯。如下基本照搬R大的內(nèi)容,不過(guò)我略做了一些修改,如下:

假設(shè)我們的Java主類的類名為JavaMainClass,下面為了區(qū)分java launcher里C/C++的main()Java層程序里的main(),把后者寫(xiě)作JavaMainClass.main()方法。

從剛進(jìn)入C/C++的main()函數(shù)開(kāi)始:

啟動(dòng)并調(diào)用HotSpot虛擬機(jī)的main()函數(shù)的線程執(zhí)行的主要邏輯如下:

main()
-> //... 做一些參數(shù)檢查
-> //... 開(kāi)啟新線程作為main線程,讓它從JavaMain()函數(shù)開(kāi)始執(zhí)行;該線程等待main線程執(zhí)行結(jié)束


在如上線程中會(huì)啟動(dòng)另外一個(gè)線程執(zhí)行JavaMain()函數(shù),如下:

JavaMain()
-> //... 找到指定的JVM
-> //... 加載并初始化JVM
-> //... 根據(jù)Main-Class指定的類名加載JavaMainClass
-> //... 在JavaMainClass類里找到名為"main"的方法,簽名為"([Ljava/lang/String;)V",修飾符是public的靜態(tài)方法
-> (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); // 通過(guò)JNI調(diào)用JavaMainClass.main()方法


以上步驟都還在java launcher的控制下;當(dāng)控制權(quán)轉(zhuǎn)移到JavaMainClass.main()方法之后就沒(méi)java launcher什么事了,等JavaMainClass.main()方法返回之后java launcher才接手過(guò)來(lái)清理和關(guān)閉JVM。

下面看一下調(diào)用Java主類main()方法時(shí)會(huì)經(jīng)過(guò)的主要方法及執(zhí)行的主要邏輯,如下:

// HotSpot VM里對(duì)JNI的CallStaticVoidMethod的實(shí)現(xiàn)。留意要傳給Java方法的參數(shù)
// 以C的可變長(zhǎng)度參數(shù)傳入,這個(gè)函數(shù)將其收集打包為JNI_ArgumentPusherVaArg對(duì)象
-> jni_CallStaticVoidMethod()  
 
     // 這里進(jìn)一步將要傳給Java的參數(shù)轉(zhuǎn)換為JavaCallArguments對(duì)象傳下去    
     -> jni_invoke_static()  
       
        // 真正底層實(shí)現(xiàn)的開(kāi)始。這個(gè)方法只是層皮,把JavaCalls::call_helper()
        // 用os::os_exception_wrapper()包裝起來(lái),目的是設(shè)置HotSpot VM的C++層面的異常處理
        -> JavaCalls::call()   
     
           -> JavaCalls::call_helper()
              -> //... 檢查目標(biāo)方法是否為空方法,是的話直接返回
              -> //... 檢查目標(biāo)方法是否“首次執(zhí)行前就必須被編譯”,是的話調(diào)用JIT編譯器去編譯目標(biāo)方法
              -> //... 獲取目標(biāo)方法的解釋模式入口from_interpreted_entry,下面將其稱為entry_point
              -> //... 確保Java棧溢出檢查機(jī)制正確啟動(dòng)
              -> //... 創(chuàng)建一個(gè)JavaCallWrapper,用于管理JNIHandleBlock的分配與釋放,
                 // 以及在調(diào)用Java方法前后保存和恢復(fù)Java的frame pointer/stack pointer

              //... StubRoutines::call_stub()返回一個(gè)指向call stub的函數(shù)指針,
              // 緊接著調(diào)用這個(gè)call stub,傳入前面獲取的entry_point和要傳給Java方法的參數(shù)等信息
              -> StubRoutines::call_stub()(...) 
                 // call stub是在VM初始化時(shí)生成的。對(duì)應(yīng)的代碼在
                 // StubGenerator::generate_call_stub()函數(shù)中
                 -> //... 把相關(guān)寄存器的狀態(tài)調(diào)整到解釋器所需的狀態(tài)
                 -> //... 把要傳給Java方法的參數(shù)從JavaCallArguments對(duì)象解包展開(kāi)到解釋模
                    // 式calling convention所要求的位置
                 -> //... 跳轉(zhuǎn)到前面?zhèn)魅氲膃ntry_point,也就是目標(biāo)方法的from_interpreted_entry

                    -> //... 在-Xcomp模式下,實(shí)際跳入的是i2c adapter stub,將解釋模式calling convention
                       // 傳入的參數(shù)挪到編譯模式calling convention所要求的位置
                           -> //... 跳轉(zhuǎn)到目標(biāo)方法被JIT編譯后的代碼里,也就是跳到 nmethod 的 VEP 所指向的位置
                                -> //... 正式開(kāi)始執(zhí)行目標(biāo)方法被JIT編譯好的代碼 <- 這里就是"main()方法的真正入口"

后面3個(gè)步驟是在編譯執(zhí)行的模式下,不過(guò)后續(xù)我們從解釋執(zhí)行開(kāi)始研究,所以需要為虛擬機(jī)配置-Xint選項(xiàng),有了這個(gè)選項(xiàng)后,Java主類的main()方法就會(huì)解釋執(zhí)行了。

在調(diào)用Java主類main()方法的過(guò)程中,我們看到了虛擬機(jī)是通過(guò)JavaCalls::call()函數(shù)來(lái)間接調(diào)用main()方法的,下一篇我們研究一下具體的調(diào)用邏輯。

到此這篇關(guān)于關(guān)于Java虛擬機(jī)HotSpot的文章就介紹到這了,更多相關(guān)Java虛擬機(jī)HotSpot內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 高分面試分析jvm如何實(shí)現(xiàn)多態(tài)

    高分面試分析jvm如何實(shí)現(xiàn)多態(tài)

    這篇文章主要介紹了講解了在面試中jvm如何實(shí)現(xiàn)多態(tài),怎樣回答才能得到高分的問(wèn)題分析,有需要的朋友可以借鑒參考下,祝大家早日升職加薪多多進(jìn)步
    2022-01-01
  • java中String的常見(jiàn)用法總結(jié)

    java中String的常見(jiàn)用法總結(jié)

    以下是關(guān)于string的七種用法,注意哦,記得要時(shí)常去查看java的API文檔,那個(gè)里面也有很詳細(xì)的介紹
    2013-10-10
  • Java 超詳細(xì)講解hashCode方法

    Java 超詳細(xì)講解hashCode方法

    在 Java 應(yīng)用程序執(zhí)行期間,在同一對(duì)象上多次調(diào)用 hashCode 方法時(shí),必須一致地返回相同的整數(shù),前提是對(duì)象上 equals 比較中所用的信息沒(méi)有被修改。從某一應(yīng)用程序的一次執(zhí)行到同一應(yīng)用程序的另一次執(zhí)行,該整數(shù)無(wú)需保持一致
    2022-04-04
  • 自動(dòng)配置@EnableAutoConfiguration問(wèn)題

    自動(dòng)配置@EnableAutoConfiguration問(wèn)題

    這篇文章主要介紹了自動(dòng)配置@EnableAutoConfiguration問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Java中的對(duì)象和對(duì)象引用實(shí)例淺析

    Java中的對(duì)象和對(duì)象引用實(shí)例淺析

    這篇文章主要介紹了Java中的對(duì)象和對(duì)象引用,實(shí)例分析了對(duì)象與對(duì)象引用的概念與相關(guān)使用技巧,需要的朋友可以參考下
    2015-05-05
  • 簡(jiǎn)單了解JAVA NIO

    簡(jiǎn)單了解JAVA NIO

    這篇文章主要介紹了JAVA NIO的的相關(guān)資料,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 只用400行Java代碼就能實(shí)現(xiàn)的飛翔的小鳥(niǎo)游戲

    只用400行Java代碼就能實(shí)現(xiàn)的飛翔的小鳥(niǎo)游戲

    今天給大家?guī)?lái)的是關(guān)于Java實(shí)戰(zhàn)的相關(guān)知識(shí),文章圍繞著只用400行Java代碼就能實(shí)現(xiàn)的飛翔的小鳥(niǎo)游戲展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java明文密碼三重加密方法

    java明文密碼三重加密方法

    這篇文章主要介紹了java明文密碼加密,對(duì)一個(gè)明文密碼進(jìn)行了三重加密:第一層?xùn)艡谝淮?,第二層在柵欄一次,第三層在一次摩斯加密,感興趣的小伙伴們可以參考一下
    2016-07-07
  • java控制臺(tái)輸出圖書(shū)館管理系統(tǒng)

    java控制臺(tái)輸出圖書(shū)館管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java控制臺(tái)輸出圖書(shū)館管理系統(tǒng),只用java代碼不用數(shù)據(jù)庫(kù)和GUI等,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • springmvc+Hibernate+JPA(混合事務(wù))解讀

    springmvc+Hibernate+JPA(混合事務(wù))解讀

    在Spring項(xiàng)目中,Spring Data JPA作為一種持久層框架,因其簡(jiǎn)化數(shù)據(jù)庫(kù)操作而受到青睞,但在將其引入使用Hibernate的舊項(xiàng)目時(shí),可能會(huì)遇到事務(wù)處理問(wèn)題,解決方案包括配置兩種事務(wù)管理器:Hibernate事務(wù)管理器和JPA事務(wù)管理器
    2024-09-09

最新評(píng)論

晋宁县| 策勒县| 吴江市| 商水县| 屏东市| 遂川县| 江北区| 定边县| 特克斯县| 涡阳县| 枣阳市| 四平市| 喀喇| 永昌县| 台南市| 章丘市| 牡丹江市| 灌云县| 陇川县| 汕尾市| 三门峡市| 黄骅市| 铜川市| 金川县| 灵璧县| 邮箱| 江门市| 潞城市| 犍为县| 四子王旗| 治多县| 获嘉县| 兴仁县| 沙河市| 桂阳县| 新营市| 平阴县| 安乡县| 额济纳旗| 马山县| 六枝特区|