[英]How does the JVM know what line programs throw exceptions in?
我想知道JVM如何檢測崩潰,具體來說,它是如何知道它崩潰的代碼行。
以下是代碼的示例部分:
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
ArrayList<String> crashMe = new ArrayList<String>(0);
crashMe.get(1);
}
}
這是崩潰消息(通過repl.it的 OpenJDK 10.0.2):
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at Main.main(Main.java:8)
迄今為止所有預期的行為。
但JVM如何知道我在第8行崩潰了? 在編譯java代碼時是否忽略了新行? 為什么jdk.internal包甚至無法拋出異常,當它們對除了JVM開發人員以外的任何人都沒用?
感謝任何提前給我一些見解的人。
但JVM如何知道我在第8行崩潰了?
看一下java.lang.Throwable
的構造函數:
public Throwable() {
fillInStackTrace();
}
fillInStackTrace
方法使用JVM本身實現的本機代碼填充當前堆棧跟蹤。 堆棧跟蹤本身只是一個StackTraceElement
數組,每個數組都包含代碼路徑中的類,方法,文件名和行號,這也是我們創建Exception的過程。 然后將堆棧跟蹤存儲在Throwable
實例中,以后可以打印。
順便說一下,你可以創建一個Throwable
並獲得它的堆棧跟蹤而不會實際拋出它。 所以下面的代碼:
public class Foo {
public static void main(String[] args) {
Throwable t = new Throwable();
for (StackTraceElement e : t.getStackTrace()) {
System.out.println(e);
}
System.out.println("This is the end of main()");
}
}
將打印:
Foo.main(Foo.java:4)
This is the end of main()
請注意, This is the end of main()
因為我們剛剛創建了一個異常。 我們還沒有拋出它。 這使得能夠從編譯代碼創建堆棧跟蹤。
在編譯java代碼時是否忽略了新行?
編譯時? 是。 創建堆棧跟蹤時? 不可以。字節代碼包含轉換為該字節代碼的源代碼指令的行號。
為什么jdk.internal包甚至無法拋出異常,當它們對除了JVM開發人員以外的任何人都沒用?
首先,JVM開發人員也是人。 他們應該像其他人一樣有例外。
其次,您所看到的異常似乎源自jdk.internal.util
,但這只是因為ArrayList
使用“internal”前置條件實用程序來檢查邊界。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.