Java 中的异常处理在内部是如何工作的?
How does exception handling work internally in Java?
try
{
}
catch(ExceptionType name)
{
}
我特别不能理解的一点是Catch Block的说法。我们写“catch(ExceptionType name)” 但是“name”到底是什么?如果“ExceptionType”是class,“name”不应该是对象的引用吗?就算是引用,既然我们还没有创建任何对象,那么它到底包含什么呢?
现在我想出了这个关于异常处理的理论 - 请纠正我,我理解错了。
案例 1 - 假设不存在 TRY,CATCH 块存在 - 如果发生错误,异常处理程序自动生成一个异常对象[基于异常的 class] 和将其移交给 JVM,然后移交给 JVM,然后 returns 将在 运行 时间
显示的函数或崩溃错误
案例 2 - 如果程序员编写了一个 TRY CATCH 块 - 如果发生错误,异常处理程序生成一个异常对象[基于异常的 class] 和然后它不会转到 JVM,而是首先查看 catch 块并尝试将引用变量与异常对象相匹配。如果匹配发生,异常处理程序将该对象交给 catch 块引用,然后程序员可以 return 他或她选择的函数。但是,如果匹配没有发生,异常处理程序会将异常对象交还给 JVM。
这就是异常处理的工作方式吗?
如果我完全理解你的问题,this 可能就是你要找的。由于 Java 是一种解释型语言,当 JVM 在执行字节码时发现正确的错误,它会跳转到您在 except 块中编写的块的字节码,从而形成 new SomeException()
,这是基本上是有关错误的信息对象,并将其作为局部变量参数传递给您的代码 ExceptionType name
.
参考你的没有 try / catch 的例子,它只需要抛出一个错误,打印堆栈跟踪,然后错误退出,并且没有实例化 SomeException 对象。希望我能帮上忙。一些可能感兴趣的链接是 here, here, and maybe here (similar question).
What exactly is "name" though?
name
就像一个 局部变量 ,它被分配了抛出的异常。或者你可以认为它是一个方法参数。
If "ExceptionType" is class, shouldn't "name" be reference to an object?
两者都是:ExceptionType
是一个 class,name
是一个对象引用。
we haven't created any object, what exactly does it contain?
无论抛出异常的逻辑是什么,都会使用 new
运算符创建它,这就是为什么 throw
语句几乎总是紧跟在 new
运算符之后,例如throw new IllegalArgumentException()
.
如果是内置异常(如 NullPointerException
、WhosebugError
、ArrayIndexOutOfBoundsException
等),JVM 运行时会创建异常。
CASE 1 - SUPPOSING NO TRY, CATCH BLOCK EXISTS
CASE 2 - IF PROGRAMMER HAS WRITTEN A TRY CATCH BLOCK
If an error occurs, the exception handler automatically generates an exception object ...
您的术语不正确:“异常处理程序”是处理抛出的异常的代码。参见例如UncaughtExceptionHandler
.
如果发生错误,JVM 运行时将创建并抛出异常,无论是否存在 try-catch
语句。
从那以后,异常的处理都是一样的,不管是系统抛出的异常,还是我们throw
语句抛出的自定义异常。
让我解释一下JVM 是如何处理异常的?
每当在方法内部发生异常时,该方法都会创建一个称为异常对象的对象,并将其传递给 运行 时间系统 (JVM)。此异常对象包含该特定异常的详细信息以及发生异常的程序的当前状态。创建异常对象并将其处理到 运行 时间系统称为抛出 异常。可能有一个方法列表,这些方法已被调用以到达发生异常的方法。这个有序的方法列表称为 Call Stack。现在将发生以下过程。
- 运行-时间系统搜索调用堆栈以查找包含可以处理发生的异常的代码块的方法。代码块称为异常处理程序。
- 运行-时间系统从发生异常的方法开始搜索,按照调用方法的相反顺序在调用堆栈中进行。
- 如果它找到合适的处理程序,则将发生的异常传递给它。适当的处理程序意味着抛出的异常对象的类型与它可以处理的异常对象的类型相匹配。
- 如果运行-时间系统搜索调用堆栈上的所有方法并且找不到合适的处理程序那么运行-时间系统将异常对象移交给默认异常处理程序,它是 运行 时间系统的一部分。此处理程序按以下格式打印异常信息并异常终止程序。
现在在java
中,try catch finally 块中的流量控制是如何工作的
try-catch 子句或 try-catch-finally 子句中的控制流:
一种。 案例 1:异常发生在 try 块中,并在 catch 块中处理。
b. 情况 2: try 块中发生的异常未在 catch 块中处理。
C。 情况 3:try-block 中没有出现异常
try-finally 子句
一种。 案例 1:try 块中发生异常。
b. 情况 2:try 块中没有发生异常。
有关try-catch-finally 块中的流控制工作的更多信息,您可以参考此link
If ExceptionType
is class, shouldn't name
be reference to an object? Even if it is a reference, since we haven't created any object, what exactly does it contain?
对您的问题/误解的简单回答是捕获异常不会创建异常对象。相反,异常对象 是较早创建的 .
当你这样做时:
throw new SomeException("message");
new
正在显式创建异常对象。
当你这样做时:
SomeClass foo = null;
foo.someMethod();
JVM 将创建一个 NullPointerException
对象。
在任何一种情况下,都将是那些对象被分配给catch子句中的变量; name
在你的例子中。
这也间接说明了另外一件事。当您在异常对象上调用 printStackTrace()
时,它(显然)会打印抛出异常点的堆栈跟踪。
它是如何管理的?
其实我上面说的有点不对。它是什么实际上打印的是异常对象创建点的stacktrace!(这两个点通常是相同的,但不是总是。)
实际发生的是,当异常对象被创建时(通过 new
、JVM 或本机代码)Throwable
(的祖先 class all 异常 classes) 调用了一个名为 fillInStackTrace()
的方法。这又会调用一个内部方法,该方法使用当前调用上下文的堆栈帧信息填充一个数组。
try
{
}
catch(ExceptionType name)
{
}
我特别不能理解的一点是Catch Block的说法。我们写“catch(ExceptionType name)” 但是“name”到底是什么?如果“ExceptionType”是class,“name”不应该是对象的引用吗?就算是引用,既然我们还没有创建任何对象,那么它到底包含什么呢?
现在我想出了这个关于异常处理的理论 - 请纠正我,我理解错了。
案例 1 - 假设不存在 TRY,CATCH 块存在 - 如果发生错误,异常处理程序自动生成一个异常对象[基于异常的 class] 和将其移交给 JVM,然后移交给 JVM,然后 returns 将在 运行 时间
显示的函数或崩溃错误案例 2 - 如果程序员编写了一个 TRY CATCH 块 - 如果发生错误,异常处理程序生成一个异常对象[基于异常的 class] 和然后它不会转到 JVM,而是首先查看 catch 块并尝试将引用变量与异常对象相匹配。如果匹配发生,异常处理程序将该对象交给 catch 块引用,然后程序员可以 return 他或她选择的函数。但是,如果匹配没有发生,异常处理程序会将异常对象交还给 JVM。
这就是异常处理的工作方式吗?
如果我完全理解你的问题,this 可能就是你要找的。由于 Java 是一种解释型语言,当 JVM 在执行字节码时发现正确的错误,它会跳转到您在 except 块中编写的块的字节码,从而形成 new SomeException()
,这是基本上是有关错误的信息对象,并将其作为局部变量参数传递给您的代码 ExceptionType name
.
参考你的没有 try / catch 的例子,它只需要抛出一个错误,打印堆栈跟踪,然后错误退出,并且没有实例化 SomeException 对象。希望我能帮上忙。一些可能感兴趣的链接是 here, here, and maybe here (similar question).
What exactly is "name" though?
name
就像一个 局部变量 ,它被分配了抛出的异常。或者你可以认为它是一个方法参数。
If "ExceptionType" is class, shouldn't "name" be reference to an object?
两者都是:ExceptionType
是一个 class,name
是一个对象引用。
we haven't created any object, what exactly does it contain?
无论抛出异常的逻辑是什么,都会使用 new
运算符创建它,这就是为什么 throw
语句几乎总是紧跟在 new
运算符之后,例如throw new IllegalArgumentException()
.
如果是内置异常(如 NullPointerException
、WhosebugError
、ArrayIndexOutOfBoundsException
等),JVM 运行时会创建异常。
CASE 1 - SUPPOSING NO TRY, CATCH BLOCK EXISTS
CASE 2 - IF PROGRAMMER HAS WRITTEN A TRY CATCH BLOCK
If an error occurs, the exception handler automatically generates an exception object ...
您的术语不正确:“异常处理程序”是处理抛出的异常的代码。参见例如UncaughtExceptionHandler
.
如果发生错误,JVM 运行时将创建并抛出异常,无论是否存在 try-catch
语句。
从那以后,异常的处理都是一样的,不管是系统抛出的异常,还是我们throw
语句抛出的自定义异常。
让我解释一下JVM 是如何处理异常的? 每当在方法内部发生异常时,该方法都会创建一个称为异常对象的对象,并将其传递给 运行 时间系统 (JVM)。此异常对象包含该特定异常的详细信息以及发生异常的程序的当前状态。创建异常对象并将其处理到 运行 时间系统称为抛出 异常。可能有一个方法列表,这些方法已被调用以到达发生异常的方法。这个有序的方法列表称为 Call Stack。现在将发生以下过程。
- 运行-时间系统搜索调用堆栈以查找包含可以处理发生的异常的代码块的方法。代码块称为异常处理程序。
- 运行-时间系统从发生异常的方法开始搜索,按照调用方法的相反顺序在调用堆栈中进行。
- 如果它找到合适的处理程序,则将发生的异常传递给它。适当的处理程序意味着抛出的异常对象的类型与它可以处理的异常对象的类型相匹配。
- 如果运行-时间系统搜索调用堆栈上的所有方法并且找不到合适的处理程序那么运行-时间系统将异常对象移交给默认异常处理程序,它是 运行 时间系统的一部分。此处理程序按以下格式打印异常信息并异常终止程序。
现在在java
中,try catch finally 块中的流量控制是如何工作的try-catch 子句或 try-catch-finally 子句中的控制流: 一种。 案例 1:异常发生在 try 块中,并在 catch 块中处理。 b. 情况 2: try 块中发生的异常未在 catch 块中处理。 C。 情况 3:try-block 中没有出现异常
try-finally 子句 一种。 案例 1:try 块中发生异常。 b. 情况 2:try 块中没有发生异常。
有关try-catch-finally 块中的流控制工作的更多信息,您可以参考此link
If
ExceptionType
is class, shouldn'tname
be reference to an object? Even if it is a reference, since we haven't created any object, what exactly does it contain?
对您的问题/误解的简单回答是捕获异常不会创建异常对象。相反,异常对象 是较早创建的 .
当你这样做时:
throw new SomeException("message");
new
正在显式创建异常对象。
当你这样做时:
SomeClass foo = null;
foo.someMethod();
JVM 将创建一个 NullPointerException
对象。
在任何一种情况下,都将是那些对象被分配给catch子句中的变量; name
在你的例子中。
这也间接说明了另外一件事。当您在异常对象上调用 printStackTrace()
时,它(显然)会打印抛出异常点的堆栈跟踪。
它是如何管理的?
其实我上面说的有点不对。它是什么实际上打印的是异常对象创建点的stacktrace!(这两个点通常是相同的,但不是总是。)
实际发生的是,当异常对象被创建时(通过 new
、JVM 或本机代码)Throwable
(的祖先 class all 异常 classes) 调用了一个名为 fillInStackTrace()
的方法。这又会调用一个内部方法,该方法使用当前调用上下文的堆栈帧信息填充一个数组。