An exceptional self-suppression error in try-with-resources does not come from Eclipse

I ran into an alarming situation when I expect Java to complain (via IllegalArgumentException from Throwable.addSuppressed ) about throwing the same exception twice, once from the try-with-resources block and once from the AutoCloseable class close () . I created a simple test case below which the problem is highlighted.

I am running JDK 1.7.0_65 with the following code:

 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; } } } 

When I compile and run the code above through the command line, I get the expected result, an error indicating that I was trying to self-suppress and throw an exception:

 [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) 

However, when I create and run the same code from Eclipse, I do not get the same result, I get the following:

 Exception in thread "main" java.lang.RuntimeException: My Exception at TestDoubleThrow.main(TestDoubleThrow.java:9) 

I removed the .class path after the build from the command line to make sure that Eclipse rebuilt it. Running from the debugger, I noticed that from Eclipse the code never goes into java.lang.Throwable.addSuppressed() .

Interestingly, if I build a class from Eclipse, run it from the command line, I DO NOT SEE a self-suppression error. Similarly, if I build a class from the command line and run it from Eclipse (without building from Eclipse), then I WILL DIE the error. This suggests that something is funny about how an eclipse creates a class.

I would like to know how to ensure that Eclipse can create the class in such a way as to get an error, because for my purposes it is an error, and I want it to be detectable when I create and run from Eclipse.

+5
source share
1 answer

Eclipse has its own compiler and produces different output. Code compiled using Eclipse checks to ensure that the thrown exception is equal to itself before calling Throwable.addSuppressed . You can see this with the javap tool.

See the if_acmpeq line in the output of the Eclipse compiler.

JDK behavior is more closely related to the example in the specification . You could raise a defect with the Eclipse command.

JDK / javac output:

  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 Output:

  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 

I used JDK 8 and Eclipse 4.4.

+3
source

Source: https://habr.com/ru/post/1201530/


All Articles