finalize()
?
finalize()
?
Answers:
我没有试过,所以我不知道,如果JVM将限制这样的事情,但也许你可以编译代码抛出ChuckNorrisException
,但在运行时提供了一个类定义的ChuckNorrisException
其未延伸的Throwable。
更新:
没用 它生成一个验证错误:
Exception in thread "main" java.lang.VerifyError: (class: TestThrow, method: ma\
in signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestThrow. Program will exit.
更新2:
实际上,如果禁用字节码验证程序,则可以使它正常工作!(-Xverify:none
)
更新3:
对于那些在家中跟随的人,这是完整的脚本:
创建以下类:
public class ChuckNorrisException
extends RuntimeException // <- Comment out this line on second compilation
{
public ChuckNorrisException() { }
}
public class TestVillain {
public static void main(String[] args) {
try {
throw new ChuckNorrisException();
}
catch(Throwable t) {
System.out.println("Gotcha!");
}
finally {
System.out.println("The end.");
}
}
}
编译类:
javac -cp . TestVillain.java ChuckNorrisException.java
跑:
java -cp . TestVillain
Gotcha!
The end.
注释掉“扩展RuntimeException”并仅重新编译ChuckNorrisException.java
:
javac -cp . ChuckNorrisException.java
跑:
java -cp . TestVillain
Exception in thread "main" java.lang.VerifyError: (class: TestVillain, method: main signature: ([Ljava/lang/String;)V) Can only throw Throwable objects
Could not find the main class: TestVillain. Program will exit.
未经验证即可运行:
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
Object
而不是Throwable
,该怎么办?(编译器不允许这样做,但是由于我们已经禁用了验证程序,所以也许有人可以破解该字节码来进行验证。)
在深思熟虑之后,我成功创建了一个不可捕获的异常。JulesWinnfield
但是,我选择了它的名字,而不是Chuck,因为它是蘑菇云铺设的母亲例外。此外,它可能与您的想法不完全相同,但是肯定无法抓住它。观察:
public static class JulesWinnfield extends Exception
{
JulesWinnfield()
{
System.err.println("Say 'What' again! I dare you! I double dare you!");
System.exit(25-17); // And you shall know I am the LORD
}
}
public static void main(String[] args)
{
try
{
throw new JulesWinnfield();
}
catch(JulesWinnfield jw)
{
System.out.println("There's a word for that Jules - a bum");
}
}
瞧!未捕获的异常。
输出:
跑:
再说一次“什么”!我赌你!我量你不敢!
Java结果:8
建立成功(总时间:0秒)
当我有更多时间时,我会看看是否也无法提出其他建议。
另外,请检查以下内容:
public static class JulesWinnfield extends Exception
{
JulesWinnfield() throws JulesWinnfield, VincentVega
{
throw new VincentVega();
}
}
public static class VincentVega extends Exception
{
VincentVega() throws JulesWinnfield, VincentVega
{
throw new JulesWinnfield();
}
}
public static void main(String[] args) throws VincentVega
{
try
{
throw new JulesWinnfield();
}
catch(JulesWinnfield jw)
{
}
catch(VincentVega vv)
{
}
}
导致堆栈溢出-同样,未捕获异常。
JulesWinfield
?系统在抛出之前是否会突然停止?
throw new Whatever()
实际上分为两部分:Whatever it = new Whatever(); throw it;
,并且系统在到达第二部分之前就死了。
class cn extends exception{private cn(){}}
有了这样的异常,显然必须使用System.exit(Integer.MIN_VALUE);
构造函数中的a ,因为如果您抛出这样的异常,将会发生这种情况;)
while(true){}
代替System.exit()
。
System.exit()
从通过安装其不允许其安全管理工作。这会将构造函数转换为其他异常(SecurityException),该异常可能会被捕获。
任何代码都可以捕获Throwable。因此,不,您创建的任何异常都将是Throwable的子类,并且会被捕获。
hang
自己在试图捕捉ChuckNorrisException:P
我的答案基于@jtahlborn的想法,但这是一个完全正常工作的Java程序,可以打包到JAR文件中,甚至可以作为Web应用程序的一部分部署到您喜欢的应用程序服务器中。
首先,让我们定义ChuckNorrisException
类,以便它从一开始就不会崩溃JVM(Chuck确实很喜欢崩溃的JVM BTW :)
package chuck;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
}
@Override
public Throwable getCause() {
return null;
}
@Override
public String getMessage() {
return toString();
}
@Override
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
}
@Override
public void printStackTrace(PrintStream s) {
super.printStackTrace(s);
}
}
现在Expendables
上课构造它:
package chuck;
import javassist.*;
public class Expendables {
private static Class clz;
public static ChuckNorrisException getChuck() {
try {
if (clz == null) {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("chuck.ChuckNorrisException");
cc.setSuperclass(pool.get("java.lang.Object"));
clz = cc.toClass();
}
return (ChuckNorrisException)clz.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
最后是Main
全班踢屁股:
package chuck;
public class Main {
public void roundhouseKick() throws Exception {
throw Expendables.getChuck();
}
public void foo() {
try {
roundhouseKick();
} catch (Throwable ex) {
System.out.println("Caught " + ex.toString());
}
}
public static void main(String[] args) {
try {
System.out.println("before");
new Main().foo();
System.out.println("after");
} finally {
System.out.println("finally");
}
}
}
使用以下命令编译并运行它:
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
您将获得以下输出:
before
finally
毫不奇怪-这毕竟是回旋踢:)
不能。Java中的所有异常都必须是subclass java.lang.Throwable
,尽管这可能不是一个好习惯,但是您可以捕获每种类型的异常,如下所示:
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
有关更多信息,请参见java.lang.Throwable文档。
实际上,可接受的答案不是很好,因为Java需要在未经验证的情况下运行,即代码在正常情况下将无法运行。
向AspectJ寻求真正的解决方案!
异常类:
package de.scrum_master.app;
public class ChuckNorrisException extends RuntimeException {
public ChuckNorrisException(String message) {
super(message);
}
}
方面:
package de.scrum_master.aspect;
import de.scrum_master.app.ChuckNorrisException;
public aspect ChuckNorrisAspect {
before(ChuckNorrisException chuck) : handler(*) && args(chuck) {
System.out.println("Somebody is trying to catch Chuck Norris - LOL!");
throw chuck;
}
}
样例应用程序:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
catchAllMethod();
}
private static void catchAllMethod() {
try {
exceptionThrowingMethod();
}
catch (Throwable t) {
System.out.println("Gotcha, " + t.getClass().getSimpleName() + "!");
}
}
private static void exceptionThrowingMethod() {
throw new ChuckNorrisException("Catch me if you can!");
}
}
输出:
Somebody is trying to catch Chuck Norris - LOL!
Exception in thread "main" de.scrum_master.app.ChuckNorrisException: Catch me if you can!
at de.scrum_master.app.Application.exceptionThrowingMethod(Application.java:18)
at de.scrum_master.app.Application.catchAllMethod(Application.java:10)
at de.scrum_master.app.Application.main(Application.java:5)
主题的一个变体是令人惊讶的事实,您可以从Java代码中引发未声明的检查异常。由于未在方法签名中声明它,因此编译器不会让您捕获异常本身,尽管您可以将其捕获为java.lang.Exception。
这是一个帮助程序类,可让您抛出任何已声明或未声明的内容:
public class SneakyThrow {
public static RuntimeException sneak(Throwable t) {
throw SneakyThrow.<RuntimeException> throwGivenThrowable(t);
}
private static <T extends Throwable> RuntimeException throwGivenThrowable(Throwable t) throws T {
throw (T) t;
}
}
现在throw SneakyThrow.sneak(new ChuckNorrisException());
确实抛出ChuckNorrisException,但是编译器抱怨
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
有关捕获如果ChuckNorrisException是已检查的异常则不会引发的异常。
ChuckNorrisException
Java中唯一的s应该是OutOfMemoryError
and StackOverflowError
。
实际上,您可以“捕获”它们的方式是catch(OutOfMemoryError ex)
,如果抛出异常,则a 将执行,但是该块会自动将异常重新引发给调用者。
我不认为这public class ChuckNorrisError extends Error
可以解决问题,但是您可以尝试一下。我没有找到有关扩展的文档Error
Is it possible to construct a snippet of code in java that would make a hypothetical java.lang.ChuckNorrisException uncatchable?
是的,这是答案:将您的设计设计java.lang.ChuckNorrisException
成不是的实例java.lang.Throwable
。为什么?根据定义,不可抛出的对象是不可捕获的,因为您永远无法捕捉到永远无法抛出的对象。
java.lang.ChuckNorrisException
必须是一个例外,更不用说抛出
您可以将ChuckNorris保留在内部或私人位置,并封装他或使他膨胀...
try { doChuckAction(); } catch(ChuckNorrisException cne) { /*do something else*/ }
Java中异常处理的两个基本问题是,它使用异常的类型来指示是否应基于该异常采取措施,并且假定任何基于异常进行操作(即“捕获”它)的事物都可以解决基本条件。拥有一种方法,异常对象可以通过该方法来决定应执行哪些处理程序,以及到目前为止已执行的处理程序是否已对本方法进行了充分的整理以使其满足本方法的退出条件,这将非常有用。尽管这可以用来产生“无法捕获的”异常,但还有两个更大的用途是(1)产生异常,只有当异常被真正知道如何处理它们的代码捕获时,才会被视为已处理,finally
FooException
在a finally
的展开期间的一个块中BarException
,两个异常都应沿调用堆栈传播;两者都应该是可捕获的,但是放松应该持续到两个都被捕获为止)。不幸的是,我认为没有任何方法可以使现有的异常处理代码以这种方式工作而不会破坏事物。
finally
从较早的异常中清除某个块时发生了异常,则很可能在没有其他异常的情况下,任何一个异常都可能是代码应处理并继续的事情,但是处理一个而忽略另一个将是不好的。但是,没有机制可以产生两个处理程序都可以处理的复合异常。
Foo
可以使调用的代码可以区分一个异常,该异常Foo
要么是自身抛出的,要么是故意假装自己抛出的,Foo
而不是原来预期的那样。调用其他方法。这就是“检查的”异常的概念应该是“关于”的。
很容易在当前线程上模拟未捕获的异常。这将触发未捕获异常的常规行为,从而从语义上完成工作。但是,它不一定会停止当前线程的执行,因为实际上不会引发任何异常。
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.
实际上,这在(非常罕见的)情况下很有用,例如,当Error
需要适当的处理时,但是从捕获(并丢弃)any的框架中调用该方法Throwable
。