簡體   English   中英

JVM如何知道哪些行程序拋出異常?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM