Jacoco の正確な問題を説明することはできませんが、Try With Resources がどのようにコンパイルされているかを示すことはできます。基本的に、さまざまな時点でスローされた例外を処理するために、コンパイラによって生成された多くのスイッチがあります。
次のコードを取得してコンパイルすると
public static void main(String[] args){
String a = "before";
try (CharArrayWriter br = new CharArrayWriter()) {
br.writeTo(null);
} catch (IOException e){
System.out.println(e.getMessage());
}
String a2 = "after";
}
そして逆アセンブルすると、
.method static public main : ([Ljava/lang/String;)V
.limit stack 2
.limit locals 7
.catch java/lang/Throwable from L26 to L30 using L33
.catch java/lang/Throwable from L13 to L18 using L51
.catch [0] from L13 to L18 using L59
.catch java/lang/Throwable from L69 to L73 using L76
.catch [0] from L51 to L61 using L59
.catch java/io/IOException from L3 to L94 using L97
ldc 'before'
astore_1
L3:
new java/io/CharArrayWriter
dup
invokespecial java/io/CharArrayWriter <init> ()V
astore_2
aconst_null
astore_3
L13:
aload_2
aconst_null
invokevirtual java/io/CharArrayWriter writeTo (Ljava/io/Writer;)V
L18:
aload_2
ifnull L94
aload_3
ifnull L44
L26:
aload_2
invokevirtual java/io/CharArrayWriter close ()V
L30:
goto L94
L33:
.stack full
locals Object [Ljava/lang/String; Object java/lang/String Object java/io/CharArrayWriter Object java/lang/Throwable
stack Object java/lang/Throwable
.end stack
astore 4
aload_3
aload 4
invokevirtual java/lang/Throwable addSuppressed (Ljava/lang/Throwable;)V
goto L94
L44:
.stack same
aload_2
invokevirtual java/io/CharArrayWriter close ()V
goto L94
L51:
.stack same_locals_1_stack_item
stack Object java/lang/Throwable
.end stack
astore 4
aload 4
astore_3
aload 4
athrow
L59:
.stack same_locals_1_stack_item
stack Object java/lang/Throwable
.end stack
astore 5
L61:
aload_2
ifnull L91
aload_3
ifnull L87
L69:
aload_2
invokevirtual java/io/CharArrayWriter close ()V
L73:
goto L91
L76:
.stack full
locals Object [Ljava/lang/String; Object java/lang/String Object java/io/CharArrayWriter Object java/lang/Throwable Top Object java/lang/Throwable
stack Object java/lang/Throwable
.end stack
astore 6
aload_3
aload 6
invokevirtual java/lang/Throwable addSuppressed (Ljava/lang/Throwable;)V
goto L91
L87:
.stack same
aload_2
invokevirtual java/io/CharArrayWriter close ()V
L91:
.stack same
aload 5
athrow
L94:
.stack full
locals Object [Ljava/lang/String; Object java/lang/String
stack
.end stack
goto L108
L97:
.stack same_locals_1_stack_item
stack Object java/io/IOException
.end stack
astore_2
getstatic java/lang/System out Ljava/io/PrintStream;
aload_2
invokevirtual java/io/IOException getMessage ()Ljava/lang/String;
invokevirtual java/io/PrintStream println (Ljava/lang/String;)V
L108:
.stack same
ldc 'after'
astore_2
return
.end method
バイトコードを話さない人にとって、これは次の疑似 Java とほぼ同じです。バイトコードは実際には Java 制御フローに対応していないため、goto を使用する必要がありました。
ご覧のとおり、抑制された例外のさまざまな可能性を処理する多くのケースがあります。これらすべてのケースをカバーできるのは合理的ではありません。実際、goto L59
最初の try ブロックの分岐には到達できません。最初の catch Throwable がすべての例外をキャッチするからです。
try{
CharArrayWriter br = new CharArrayWriter();
Throwable x = null;
try{
br.writeTo(null);
} catch (Throwable t) {goto L51;}
catch (Throwable t) {goto L59;}
if (br != null) {
if (x != null) {
try{
br.close();
} catch (Throwable t) {
x.addSuppressed(t);
}
} else {br.close();}
}
break;
try{
L51:
x = t;
throw t;
L59:
Throwable t2 = t;
} catch (Throwable t) {goto L59;}
if (br != null) {
if (x != null) {
try{
br.close();
} catch (Throwable t){
x.addSuppressed(t);
}
} else {br.close();}
}
throw t2;
} catch (IOException e) {
System.out.println(e)
}