Java 使用Eclipse中未出现的资源重试时出现异常自抑制错误
我遇到了一个令人不安的情况,我希望Java(通过Java 使用Eclipse中未出现的资源重试时出现异常自抑制错误,java,eclipse,suppression,Java,Eclipse,Suppression,我遇到了一个令人不安的情况,我希望Java(通过Throwable.addsupprested中的IllegalArgumentException)抱怨两次抛出相同的异常,一次来自try with resources块,一次来自AutoCloseable类的close()例程。我在下面创建了一个简单的测试用例,它突出了这个问题 我使用以下代码运行JDK 1.7.0_65: public class TestDoubleThrow { public static void main(Str
Throwable.addsupprested
中的IllegalArgumentException
)抱怨两次抛出相同的异常,一次来自try with resources块,一次来自AutoCloseable
类的close()例程。我在下面创建了一个简单的测试用例,它突出了这个问题
我使用以下代码运行JDK 1.7.0_65:
public class TestDoubleThrow {
public static void main(String[] args) {
class TestA implements AutoCloseable {
RuntimeException e;
public TestA(RuntimeException e) { this.e = e; }
@Override public void close() { throw e; }
}
RuntimeException e = new RuntimeException("My Exception");
try (TestA A = new TestA(e)) {
throw e;
}
}
}
当我通过命令行编译并运行上述代码时,我得到了预期的结果,一个错误指示我已尝试自我抑制和异常:
[coreys terminal]$ java TestDoubleThrow.java ; java TestDoubleThrow
Exception in thread "main" java.lang.IllegalArgumentException: Self-suppression not permitted
at java.lang.Throwable.addSuppressed(Throwable.java:1043)
at TestDoubleThrow.main(TestDoubleThrow.java:12)
Caused by: java.lang.RuntimeException: My Exception
at TestDoubleThrow.main(TestDoubleThrow.java:9)
但是,当我从Eclipse构建和运行相同的代码时,我不会得到相同的结果,我会得到以下结果:
Exception in thread "main" java.lang.RuntimeException: My Exception
at TestDoubleThrow.main(TestDoubleThrow.java:9)
在从命令行构建之后,我删除了.class路径,以确保Eclipse重建了它。从调试器运行时,我注意到,在Eclipse中,代码从未进入java.lang.Throwable.addsupprested()
有趣的是,如果我从Eclipse构建这个类,然后从命令行运行它,我看不到自抑制错误。类似地,如果我从命令行构建类并从Eclipse运行它(而不是从Eclipse构建),那么我确实看到了错误。这表明eclipse构建类的方式很有趣
我想知道如何确保Eclipse能够以这样一种方式构建类,即我确实得到了错误,因为就我而言,这是一个错误,我希望在从Eclipse构建和运行时能够检测到它。Eclipse有自己的编译器,并且正在生成不同的输出。Eclipse编译的代码在调用之前检查被抑制的异常是否等于自身。您可以使用javap工具看到这一点 请参阅Eclipse编译器输出中的
if\u acmpeq
行
JDK的行为更符合。您可以与Eclipse团队合作
JDK/javac输出:
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/RuntimeException
3: dup
4: ldc #3 // String My Exception
6: invokespecial #4 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
9: astore_1
10: new #5 // class TestDoubleThrow$1TestA
13: dup
14: aload_1
15: invokespecial #6 // Method TestDoubleThrow$1TestA."<init>":(Ljava/lang/RuntimeException;)V
18: astore_2
19: aconst_null
20: astore_3
21: aload_1
22: athrow
23: astore 4
25: aload 4
27: astore_3
28: aload 4
30: athrow
31: astore 5
33: aload_2
34: ifnull 63
37: aload_3
38: ifnull 59
41: aload_2
42: invokevirtual #8 // Method TestDoubleThrow$1TestA.close:()V
45: goto 63
48: astore 6
50: aload_3
51: aload 6
53: invokevirtual #9 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
56: goto 63
59: aload_2
60: invokevirtual #8 // Method TestDoubleThrow$1TestA.close:()V
63: aload 5
65: athrow
Exception table:
from to target type
21 23 23 Class java/lang/Throwable
41 45 48 Class java/lang/Throwable
21 33 31 any
publicstaticvoidmain(java.lang.String[]);
代码:
0:new#2//类java/lang/RuntimeException
3:dup
4:ldc#3//字符串我的异常
6:invokespecial#4//方法java/lang/RuntimeException。“”:(Ljava/lang/String;)V
9:astore_1
10:新的#5//class TestDoubleThrow$1TestA
13:dup
14:aload_1
15:invokespecial#6//方法TestDoubleThrow$1TestA.“:(Ljava/lang/RuntimeException;)V
18:astore_2
19:aconst_null
20:astore_3
21:aload_1
22:athrow
23:astore 4
25:aload 4
27:astore_3
28:aload 4
30:athrow
31:astore 5
33:aload_2
34:ifnull 63
37:aload_3
38:ifnull 59
41:aload_2
42:invokevirtual#8//方法TestDoubleThrow$1TestA.close:()V
45:goto 63
48:astore 6
50:aload_3
51:aload 6
53:invokevirtual#9//方法java/lang/Throwable.addsupprested:(Ljava/lang/Throwable;)V
56:goto 63
59:aload_2
60:invokevirtual#8//方法TestDoubleThrow$1TestA.close:()V
63:aload 5
65:athrow
例外情况表:
从到目标类型
212323类java/lang/Throwable
41 45 48类java/lang/Throwable
21 33 31任何
Eclipse输出:
public static void main(java.lang.String[]);
Code:
0: new #16 // class java/lang/RuntimeException
3: dup
4: ldc #18 // String My Exception
6: invokespecial #20 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
9: astore_1
10: aconst_null
11: astore_2
12: aconst_null
13: astore_3
14: new #23 // class TestDoubleThrow$1TestA
17: dup
18: aload_1
19: invokespecial #25 // Method TestDoubleThrow$1TestA."<init>":(Ljava/lang/RuntimeException;)V
22: astore 4
24: aload_1
25: athrow
26: astore_2
27: aload 4
29: ifnull 37
32: aload 4
34: invokevirtual #28 // Method TestDoubleThrow$1TestA.close:()V
37: aload_2
38: athrow
39: astore_3
40: aload_2
41: ifnonnull 49
44: aload_3
45: astore_2
46: goto 59
49: aload_2
50: aload_3
51: if_acmpeq 59
54: aload_2
55: aload_3
56: invokevirtual #31 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
59: aload_2
60: athrow
Exception table:
from to target type
24 26 26 any
14 39 39 any
publicstaticvoidmain(java.lang.String[]);
代码:
0:new#16//类java/lang/RuntimeException
3:dup
4:ldc#18//String我的例外
6:invokespecial#20//方法java/lang/RuntimeException.“:(Ljava/lang/String;)V
9:astore_1
10:aconst_null
11:astore_2
12:aconst_null
13:astore_3
14:new#23//class TestDoubleThrow$1TestA
17:dup
18:aload_1
19:invokespecial#25//methodtestdoublethrow$1TestA.“:(Ljava/lang/RuntimeException;)V
22:astore 4
24:aload_1
25:athrow
26:astore_2
27:aload 4
29:ifnull 37
32:aload 4
34:invokevirtual#28//方法TestDoubleThrow$1TestA.close:()V
37:aload_2
38:athrow
39:astore_3
40:aload_2
41:ifnonnull 49
44:aload_3
45:astore_2
46:转到59
49:aload_2
50:aload_3
51:if_acmpeq 59
54:aload_2
55:aload_3
56:invokevirtual#31//方法java/lang/Throwable.addsupprested:(Ljava/lang/Throwable;)V
59:aload_2
60:athrow
例外情况表:
从到目标类型
24 26 26任何
14 39 39任何
我使用了JDK 8和Eclipse 4.4。在查看这两种情况下的字节码时,我注意到了类似的情况。我发现这个bug作为一个例子被讨论过。无论是JDK bug还是Eclipse bug,我都不想说:)在两者之间保持一致的行为会很好,而事实上Eclipse实际上插入的代码绕过了Throwable中的代码并没有那么好。