Java 不可修补的ChuckNorriseException
是否有可能在中构造一段代码,使假设的Java 不可修补的ChuckNorriseException,java,exception,exception-handling,aop,Java,Exception,Exception Handling,Aop,是否有可能在中构造一段代码,使假设的java.lang.ChuckNorriseException不可修补 脑海中浮现的想法是使用拦截器或拦截器。任何代码都可以捕获可丢弃的内容。所以,不管你创建什么异常,它都将是Throwable的一个子类,并且会被捕获 否。Java中的所有异常都必须子类Java.lang.Throwable,尽管这可能不是一个好的实践,但您可以像这样捕获每种类型的异常: try { //Stuff } catch ( Throwable T ){ //Does
java.lang.ChuckNorriseException
不可修补
脑海中浮现的想法是使用拦截器或拦截器。任何代码都可以捕获可丢弃的内容。所以,不管你创建什么异常,它都将是Throwable的一个子类,并且会被捕获 否。Java中的所有异常都必须子类
Java.lang.Throwable
,尽管这可能不是一个好的实践,但您可以像这样捕获每种类型的异常:
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
有关更多信息,请参阅文档
如果您试图避免(必须显式处理的)错误,那么您将希望对错误或RuntimeException进行子类化。对于此类异常,显然必须使用
System.exit(Integer.MIN\u值)因为如果抛出这样的异常,就会发生这种情况;) 您抛出的任何异常都必须扩展Throwable,以便始终能够捕获它。所以答案是否定的
如果你想让它变得难以处理,你可以重写方法getCause(),getMessage()
,getStackTrace()
,toString()
来抛出另一个java.lang.ChuckNorriseException
,我还没有尝试过这个,所以我不知道它是否会限制这样的东西,但也许您可以编译抛出ChuckNorriseException
的代码,但在运行时提供不扩展Throwable的ChuckNorriseException
类定义
更新:
它不起作用。它会生成一个验证器错误:
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.");
}
}
}
运行:
注释掉“extends RuntimeException”并重新编译ChuckNorriseException.java
:
运行:
未经验证运行:
java -Xverify:none -cp . TestVillain
The end.
Exception in thread "main"
在构造函数中,您可以启动一个线程,该线程反复调用originalThread.stop(ChuckNorisException.this)
线程可以重复捕获异常,但会一直抛出异常,直到异常消失。您可以将ChuckNorris保留在内部或私有状态,并封装或跟踪它
try{docuckaction();}catch(ChuckNorriseException cne){/*做点别的*/}
Java中唯一的ChuckNorriseException
应该是OutOfMemoryError
和StackOverflower
实际上,您可以“捕获”它们,这意味着在抛出异常时将执行catch(OutOfMemoryError ex)
,但该块将自动将异常重新发送给调用方
我认为公共类ChuckNorrisError extensed Error
不起作用,但您可以尝试一下。我没有找到关于扩展错误的文档
在考虑了这一点之后,我成功地创建了一个不可跟踪的异常。然而,我选择将它命名为Jules Winnfield,而不是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)
{
}
}
导致堆栈溢出-同样,异常保持未捕获状态
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
(当然,从技术上讲,这个异常从来不会被实际抛出,但是不能抛出一个正确的ChuckNorriseException
,它首先抛出您。)Java中异常处理的两个基本问题是,它使用异常的类型来指示是否应该基于它采取操作,任何基于异常(即“捕获”它)采取行动的行为都被认为可以解决潜在的问题。如果有一种方法,异常对象可以通过它来决定应该执行哪些处理程序,以及到目前为止已经执行的处理程序是否已经清理了足够多的内容,以满足当前方法的退出条件,这将是非常有用的。虽然这可以用于生成“不可调度”异常,但两个更大的用途是:(1)生成异常,只有当它们被实际知道如何处理它们的代码捕获时才会被认为是已处理的,以及(2)允许合理地处理finally
块中发生的异常(如果在解除BarException
期间的footexception
过程中出现finally
块,则这两个异常都应向上传播到调用堆栈;这两个异常都应可捕获,但应继续解除,直到捕获到这两个异常为止)。不幸的是,我不认为有任何方法可以让现有的异常处理代码以这种方式工作而不破坏任何东西。是否可以用java构造一段代码,使假设的java.lang.ChuckNorriseException不可跟踪?
是的,答案是:设计你的java.lang.ChuckNorriseException
,这样它就不是java.lang.Throwable
。为什么?一个不可伸缩的对象从定义上来说是不可伸缩的,因为你永远抓不到永远不会被抛出的东西。我的答案基于@jtahlborn的想法,但它是一个完全有效的对象程序,它可以打包成文件,甚至可以作为应用程序的一部分部署到您喜爱的应用程序服务器
首先,让我们定义ChuckNorriseException
类,这样它从一开始就不会使JVM崩溃(Chuck非常喜欢使JVM崩溃,顺便说一句:)
现在进入“消耗品”类来构建它:
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
类
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");
}
}
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)
{
}
}
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
System.exit(1);
}
}
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);
}
}
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);
}
}
}
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
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;
}
}
try {
throw SneakyThrow.sneak(new ChuckNorrisException());
} catch (ChuckNorrisException e) {
}
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!");
}
}
Throwable exception = /* ... */;
Thread currentThread = Thread.currentThread();
Thread.UncaughtExceptionHandler uncaughtExceptionHandler =
currentThread.getUncaughtExceptionHandler();
uncaughtExceptionHandler.uncaughtException(currentThread, exception);
// May be reachable, depending on the uncaught exception handler.