根据您的说法,拦截Java应用程序中所有异常的最简单方法是什么? 是否需要AOP来提供这种功能,还是可以使用动态代理来实现,还是有其他方式? 最简单的解决方案是否也是影响执行性能的良好解决方案? 我希望听到更有经验的开发人员可能的解决方案,因为我正在努力掌握有关该主题的技术知识。
修改
感谢您提供了很好的建议,但目前的建议是否仅适用于已检查的例外情况?那些未经检查的异常,如NullPointerExceptions,如果可以捕获它们并且捕获它们的应用程序转储堆/堆栈以便在崩溃时为您提供应用程序的当前上下文,那么它会不会有用呢?
答案 0 :(得分:11)
您希望拦截每个例外的目的是什么 - 用于记录,错误报告?
可以拦截Java程序的每一行中的每个异常,但可能会产生相当大的性能损失。如果它是不可避免的,那么最好使用类似AspectJ的东西,它可以在编译时运行(即它“编织”到你的类文件中),因此比动态代理要快得多。
但我会尽量避免不惜一切代价!一般来说,我会说最好限制你想要捕获的异常的范围。您也可以查看Thread.setDefaultUncaughtExceptionHandler,我认为这对于在GUI应用程序中显示错误对话框非常有用。
答案 1 :(得分:9)
与Phil的回答类似,这里有一些示例代码,展示了如何使用未捕获的异常处理程序。这适用于已检查和未检查的异常。
编辑:更新以根据问题中的更新评论打印堆栈跟踪。
import java.lang.Thread.UncaughtExceptionHandler;
public class Test {
public static void main(String[] args) throws Exception {
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
e.printStackTrace();
}}
);
// throw new RuntimeException(); /* this works too */
throw new Exception();
}
}
答案 2 :(得分:5)
在Nate和Konamiman ......你所建议的内容根本不起作用,也没有回答OP的问题。
如果OP从你的try / catch中启动一个新线程怎么办?
例如:
public static void main(String[] args) {
try {
final Thread t = new Thread( new Runnable() {
public void run() {
System.out.println( 3 / Math.min(0,4) );
}
} );
t.start();
catch(Throwable t) {
...
}
}
然后你没有抓住异常。
正确的方法是使用Thread.setDefaultUncaughtExceptionHandler。
答案 3 :(得分:3)
public static void main(String[] args) {
try {
...
catch(Throwable t) {
...
}
}
答案 4 :(得分:0)
更重要的是,除了捕获所有异常之外,还有什么可以捕获异常:
除非您可以对此做些什么,否则不要捕获异常。如果你无法做任何事情,要么让它冒泡到一个新的水平或抓住它,重新包装它作为一个更具体的例外并重新抛出它。
总是有一个全局异常处理块(比如在Nate的回答中)来捕捉你在任何地方都无法处理的任何错误,这样你就可以稍微优雅地失败。
答案 5 :(得分:0)
如果您只想捕获异常,则try / catch块就足够了。如果你想阻止它们被抛出或者做一些日志记录或包装,你可能需要一些AOP才能做到这一点。 AspectJ将很好地处理它,但要注意潜在的性能瓶颈。
动态代理仅在代理方法时才有效,因此如果抛出任何异常并在代理对象的执行中捕获,则代理无法拦截异常。
要考虑的一件事是,您是要捕获所有异常,还是仅检查异常。为了捕获所有异常,AspectJ的around throwing
或after throwing
建议将围绕每个方法编织一些处理,这涉及在每个方法调用时创建JoinPoint对象和合成方法。这通常不是问题,除非进程处于紧密循环中,垃圾收集可以通过屋顶。
答案 6 :(得分:0)
对于所有那些质疑需要捕获所有例外的人......
有一个很多有效理由来捕获所有例外:
请注意,Java 本身会拦截EDT(事件调度线程)上的所有异常,并在EDT死亡时生成新的EDT。您可以考虑使用一种“自我修复”软件。 EDT死亡并不是闻所未闻的,并不能完全阻止应用程序正常运行(相反)。 (并且,是的,Swing和AWT有一些错误,只需看看Sun bug游行;)
可以说任何自尊软件都应该考虑到一个无法预料的异常情况(你所发布的所有软件都是100%无错误且永远不会获得新版本,错误修复版本?)并做一些事情这种不可预见的异常发生时很聪明。
'聪明的东西'可能会阻止软件崩溃(比如在EDT案例中),警告用户,发送报告等等。
回答质疑是否需要做这样的事情,或者建议这样做是不好的做法,应该恕我直言。