2014-09-01 34 views
5

我遇到了一个令人不安的情况,我期望Java通过从(从Throwable.addSuppressed)投诉两次抛出相同的异常,一次从try-带有资源块和从AutoCloseable类的关闭()例程。我已经创建了一个简单的测试用例,其中突出显示了问题。在Eclipse中尝试资源时出现异常自我压抑错误

我运行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.addSuppressed()。有趣的是,如果我从Eclipse构建类,然后从命令行运行它,我不会看到自我抑制错误。同样,如果我从命令行构建类并从Eclipse运行它(无需从Eclipse构建),那么我会看到错误。这表明对于eclipse如何构建类是有趣的。

我想知道如何确保Eclipse能够以这样一种方式构建类,使得我得到错误,因为对我而言,这是一个错误,我希望能够在构建和运行时检测到它来自Eclipse。

回答

3

Eclipse有它自己的编译器,并产生不同的输出。由Eclipse编译的代码在调用Throwable.addSuppressed之前检查是否抑制异常等于它自己。您可以使用javap工具来查看此信息。

请参阅Eclipse编译器输出中的if_acmpeq行。

JDK行为更紧密地遵循the example in the specification。你可以在Eclipse团队中使用raise a defect

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 

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 

我用JDK 8和Eclipse 4.4。

+0

在两种情况下查看字节码时,我都注意到了类似的情况。我发现这个bug是作为[JDK bug]在这里讨论的(https://bugs.openjdk.java.net/browse/JDK-8042377)。无论是JDK错误还是Eclipse错误都不适合我说:)在两者之间保持一致的行为会很好,事实上Eclipse实际上插入了绕过Throwable的代码并不是那么好。 – CoreyP 2014-09-03 05:30:36

相关问题