https://github.com/FranzHaidnor/haidnorJVM
使用 Java17 編寫的 Java 虛擬機器器
+
,-
,*
,^
,%
,++
,--
)==
,!=
,>
,<
,>=
,<=
)&
,|
,^
,~
,<<
,>>
,>>>
)=
,+=
,-=
,*=
,%=
,<<=
,>>=
,&=
,^=
,|=
)while
,do...while
,for
,foreach
)if
,if...else
,if...else if
)在 resources\simplelogger.properties
檔案中修改紀錄檔輸出級別,一般使用 debug
、info
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 "你好 世界";
}
}
每一個 匚
結構圖形,都表示一個 JVM 執行緒棧中的棧幀
修改 haidnorJVM.properties
檔案中的內容。設定 rt.jar 的絕對路徑,例如rt.jar=D:/Program Files/Java/jdk1.8.0_361/jre/lib/rt.jar
在 IDE 中開啟專案中 test 目錄下的 haidnor.jvm.test.TestJVM.java
檔案。 這是 haidnorJVM 的主要測試類, 裡面的測試方法可以解析載入執行 .class 位元組碼檔案。
public class TestJVM {
/**
* haidnorJVM 會載入 HelloWorld.java 在 target 目錄下的編譯後的位元組碼檔案,然後執行其中的 `main(String[] args)` 方法。
* 你可以使用打斷點的方式看到 haidnorJVM 是如何解釋執行 Java 位元組碼的。
* 值得注意的是,這種方式編譯執行的位元組碼檔案是基於 java17 版本的。
*/
@Test
public void test() {
runMainClass(HelloWorld.class);
}
}
haidnorJVM.jar
檔案public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
java -jar haidnorJVM.jar -class R:\HelloWorld.class
。注意! 需要 class 檔案的絕對路徑haidnorJVM.jar
檔案Main-Class
屬性 (含有 public static void main(String[] args)
方法的主類資訊)java -jar haidnorJVM.jar -class R:\demo.jar
。注意! 需要 jar 檔案的絕對路徑由於 haidnorJVM 目前執行 JDK 自帶的類是使用反射解決的,因此 haidnorJVM 使用 JDK17 執行部分 JDK 自帶的類時會存在一些問題,例如執行以下程式碼將會丟擲異常
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)
它表示嘗試通過反射來存取一個方法或欄位,但該方法或欄位的可存取性限制導致無法存取。
這個限制通常是由於 Java 模組系統引起的。模組系統允許將程式碼劃分為獨立的模組,
並控制模組之間的存取許可權。以上異常的原因是 module java.base does not "opens java.util" to unnamed module,也就是說 java.base 模組沒有向未命名模組開放 java.util 包
解決方法:
啟動 haidnorJVM 時新增 JVM 引數 --add-opens java.base/java.util=ALL-UNNAMED
繞過存取性限制
微訊號: haidnor