欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

利用Java編寫(xiě)一個(gè)Java虛擬機(jī)

 更新時(shí)間:2023年07月30日 08:54:48   作者:Haidnor  
這篇文章主要為大家詳細(xì)介紹了如何使用 Java17 編寫(xiě)的 Java 虛擬機(jī),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的可以了解下

github 項(xiàng)目鏈接

https://github.com/FranzHaidnor/haidnorJVM

haidnorJVM

使用 Java17 編寫(xiě)的 Java 虛擬機(jī)

意義

  • 紙上得來(lái)終覺(jué)淺,絕知此事要躬行。只學(xué)習(xí) JVM 機(jī)制和理論,很多時(shí)候任然覺(jué)得缺乏那種大徹大悟之感
  • 使用簡(jiǎn)單的方式實(shí)現(xiàn) JVM,用于學(xué)習(xí)理解 JVM 運(yùn)行原理

主要技術(shù)選型

實(shí)現(xiàn)功能

  • 實(shí)現(xiàn)了 99% 的 JVM 字節(jié)碼指令。參照 JVM 字節(jié)碼規(guī)范實(shí)現(xiàn) The Java Virtual Machine Instruction Set
  • 支持算數(shù)運(yùn)算符 (+,-,*,^,%,++,--)
  • 支持關(guān)系運(yùn)算符 (==,!=,>,<,>=,<=)
  • 支持位運(yùn)算符 (&,|,^,~,<<,>>,>>>)
  • 支持賦值運(yùn)算符 (=,+=,-=,*=,%=,<<=,>>=,&=,^=,|=)
  • 支持 instanceof 運(yùn)算符
  • 支持循環(huán)結(jié)構(gòu)代碼 (while,do...while,for,foreach)
  • 支持條件結(jié)構(gòu)代碼 (if,if...else,if...else if)
  • 支出創(chuàng)建自定義類
  • 支持創(chuàng)建對(duì)象、訪問(wèn)對(duì)象
  • 支持抽象類
  • 支持多態(tài)繼承、接口
  • 支持訪問(wèn)靜態(tài)方法
  • 支持訪問(wèn)對(duì)象方法
  • 支持 JDK 中自帶的 Java 類
  • 支持反射
  • 支持異常
  • 枚舉 (開(kāi)發(fā)中...)
  • switch 語(yǔ)法 (開(kāi)發(fā)中...)
  • lambda 表達(dá)式 (開(kāi)發(fā)中...)

局限性

不支持多線程

不支持多維數(shù)組

暫無(wú)雙親委派機(jī)制實(shí)現(xiàn)

無(wú)垃圾收集器實(shí)現(xiàn)。垃圾回收依靠宿主 JVM

快速體驗(yàn)

你需要準(zhǔn)備什么

  • 集成開(kāi)發(fā)環(huán)境 (IDE)。你可以選擇包括 IntelliJ IDEA、Visual Studio Code 或 Eclipse 等等
  • JDK 17。并配置 JAVA_HOME
  • JDK 8。haidnorJVM 的主要目標(biāo)是運(yùn)行 Java8 本版的字節(jié)碼文件。(但 haidnorJVM 沒(méi)有強(qiáng)制要求字節(jié)碼文件是 Java8 版本)
  • Maven

配置 haidnorJVM

配置日志輸出級(jí)別

在 resources\simplelogger.properties 文件中修改日志輸出級(jí)別,一般使用 debug、info

  • 配置 info 級(jí)別將不會(huì)看到任何 haidnorJVM 內(nèi)部運(yùn)行信息
  • 配置 debug 級(jí)別下運(yùn)行將會(huì)非常友好的輸出 JVM 正在執(zhí)行的棧信息
public class Demo5 {
    public static void main(String[] args) {
        String str = method1("hello world");
        method1(str);
    }
    public static String method1(String s) {
        return method2(s);
    }
    public static String method2(String s) {
        return method3(s);
    }
    public static String method3(String s) {
        System.out.println(s);
        return "你好 世界";
    }
}

每一個(gè)  結(jié)構(gòu)圖形,都表示一個(gè) JVM 線程棧中的棧幀

配置 rt.jar 路徑

修改 haidnorJVM.properties 文件中的內(nèi)容。配置 rt.jar 的絕對(duì)路徑,例如rt.jar=D:/Program Files/Java/jdk1.8.0_361/jre/lib/rt.jar

運(yùn)行單元測(cè)試用例

在 IDE 中打開(kāi)項(xiàng)目中 test 目錄下的 haidnor.jvm.test.TestJVM.java 文件。 這是 haidnorJVM 的主要測(cè)試類, 里面的測(cè)試方法可以解析加載運(yùn)行 .class 字節(jié)碼文件。

public class TestJVM {
   /**
    *  haidnorJVM 會(huì)加載 HelloWorld.java 在 target 目錄下的編譯后的字節(jié)碼文件,然后運(yùn)行其中的 `main(String[] args)` 方法。
    *  你可以使用打斷點(diǎn)的方式看到 haidnorJVM 是如何解釋運(yùn)行 Java 字節(jié)碼的。
    *  值得注意的是,這種方式編譯運(yùn)行的字節(jié)碼文件是基于 java17 版本的。
    */
   @Test
   public void test() {
      runMainClass(HelloWorld.class);
   }
}

運(yùn)行 .class 文件

  • 使用 maven 命令將 haidnorJVM 編譯打包,得到 haidnorJVM.jar 文件
  • 編寫(xiě)一個(gè)簡(jiǎn)單的程序,例如以下代碼
public class HelloWorld {
   public static void main(String[] args) {
     System.out.println("HelloWorld");
   }
}
  • 編譯代碼,得到 HelloWorld.class 文件 (推薦使用 JDK8 進(jìn)行編譯)
  • 使用 haidnorJVM 運(yùn)行程序。執(zhí)行命令 java -jar haidnorJVM.jar -class R:\HelloWorld.class。注意! 需要 class 文件的絕對(duì)路徑

運(yùn)行 .jar 文件

  • 使用 maven 命令將 haidnorJVM 編譯打包,得到 haidnorJVM.jar 文件
  • 編寫(xiě)一個(gè) java 項(xiàng)目編譯打包成 .jar 文件,例如 demo.jar。要求 .jar 文件中的 META-INF/MANIFEST.MF 文件內(nèi)有 Main-Class 屬性 (含有 public static void main(String[] args) 方法的主類信息)
  • 使用 haidnorJVM 運(yùn)行程序。執(zhí)行命令 java -jar haidnorJVM.jar -class R:\demo.jar。注意! 需要 jar 文件的絕對(duì)路徑

存在的問(wèn)題

由于 haidnorJVM 目前運(yùn)行 JDK 自帶的類是使用反射解決的,因此 haidnorJVM 使用 JDK17 運(yùn)行部分 JDK 自帶的類時(shí)會(huì)存在一些問(wèn)題,例如運(yùn)行以下代碼將會(huì)拋出異常

public class Demo {
    public static void main(String[] args) {
        List<Integer> list = List.of(1, 2, 3, 4, 5);
        list.add(6);
    }
}
java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.ImmutableCollections$AbstractImmutableCollection.add(java.lang.Object) accessible: module java.base does not "opens java.util" to unnamed module @18769467
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
	at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
	at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)

它表示嘗試通過(guò)反射來(lái)訪問(wèn)一個(gè)方法或字段,但該方法或字段的可訪問(wèn)性限制導(dǎo)致無(wú)法訪問(wèn)。

這個(gè)限制通常是由于 Java 模塊系統(tǒng)引起的。模塊系統(tǒng)允許將代碼劃分為獨(dú)立的模塊,并控制模塊之間的訪問(wèn)權(quán)限。以上異常的原因是 module java.base does not "opens java.util" to unnamed module,也就是說(shuō) java.base 模塊沒(méi)有向未命名模塊開(kāi)放 java.util 包

解決方法:啟動(dòng) haidnorJVM 時(shí)添加 JVM 參數(shù) --add-opens java.base/java.util=ALL-UNNAMED 繞過(guò)訪問(wèn)性限制

以上就是利用Java編寫(xiě)一個(gè)Java虛擬機(jī)的詳細(xì)內(nèi)容,更多關(guān)于Java虛擬機(jī)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Spring Cloud Stream使用延遲消息實(shí)現(xiàn)定時(shí)任務(wù)(RabbitMQ)

    詳解Spring Cloud Stream使用延遲消息實(shí)現(xiàn)定時(shí)任務(wù)(RabbitMQ)

    這篇文章主要介紹了詳解Spring Cloud Stream使用延遲消息實(shí)現(xiàn)定時(shí)任務(wù)(RabbitMQ),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • 基于Spring的RPC通訊模型的使用與比較

    基于Spring的RPC通訊模型的使用與比較

    這篇文章主要介紹了基于Spring的RPC通訊模型的使用與比較,詳細(xì)的介紹了RMI、Caucho的Hessian和Burlap以及Spring自帶的HTTP invoker,感興趣的可以了解一下
    2018-09-09
  • Java16 JDK安裝并設(shè)置環(huán)境變量的方法步驟

    Java16 JDK安裝并設(shè)置環(huán)境變量的方法步驟

    突然想起自己大學(xué)剛接觸java的時(shí)候,要下載JDK和配置環(huán)境變量,那時(shí)候我上網(wǎng)找了很多教學(xué),本文就詳細(xì)的介紹一下Java16 JDK安裝并設(shè)置環(huán)境變量,感興趣的可以了解一下
    2021-09-09
  • springboot整合RabbitMQ中死信隊(duì)列的實(shí)現(xiàn)

    springboot整合RabbitMQ中死信隊(duì)列的實(shí)現(xiàn)

    死信是無(wú)法被消費(fèi)的消息,產(chǎn)生原因包括消息TTL過(guò)期、隊(duì)列最大長(zhǎng)度達(dá)到以及消息被拒絕且不重新排隊(duì),RabbitMQ的死信隊(duì)列機(jī)制能夠有效防止消息數(shù)據(jù)丟失,適用于訂單業(yè)務(wù)等場(chǎng)景,本文就來(lái)介紹一下
    2024-10-10
  • springboot上傳圖片文件步驟詳解

    springboot上傳圖片文件步驟詳解

    這篇文章主要介紹了springboot上傳圖片文件步驟詳解,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Spring集成Redis詳解代碼示例

    Spring集成Redis詳解代碼示例

    這篇文章主要介紹了Spring集成Redis詳解代碼示例,介紹了Eclipse工程結(jié)構(gòu),POM依賴,Spring配置,Redis配置信息以及Java代碼等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Java中異常打印輸出的常見(jiàn)方法總結(jié)

    Java中異常打印輸出的常見(jiàn)方法總結(jié)

    Java異常是在Java應(yīng)用中的警報(bào)器,下面這篇文章主要給大家介紹了關(guān)于Java中異常打印輸出的常見(jiàn)方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-07-07
  • 使用spring攔截器實(shí)現(xiàn)日志管理實(shí)例

    使用spring攔截器實(shí)現(xiàn)日志管理實(shí)例

    本篇文章主要介紹了使用spring攔截器實(shí)現(xiàn)日志管理實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Java的RocketMq隊(duì)列之消息可靠性詳解

    Java的RocketMq隊(duì)列之消息可靠性詳解

    這篇文章主要介紹了Java的RocketMq隊(duì)列之消息可靠性詳解,生產(chǎn)者通過(guò)網(wǎng)絡(luò)發(fā)送消息給 Broker,當(dāng) Broker 收到之后,將會(huì)返回確認(rèn)響應(yīng)信息給 Producer,所以生產(chǎn)者只要接收到返回的確認(rèn)響應(yīng),就代表消息在生產(chǎn)階段未丟失,需要的朋友可以參考下
    2024-01-01
  • Spring如何集成ibatis項(xiàng)目并實(shí)現(xiàn)dao層基類封裝

    Spring如何集成ibatis項(xiàng)目并實(shí)現(xiàn)dao層基類封裝

    這篇文章主要介紹了Spring如何集成ibatis項(xiàng)目并實(shí)現(xiàn)dao層基類封裝,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論