我试图通过使用常规try-catch-finally语句重新创建新的try-with-resources statement来了解它。给出以下使用Java 7 try-with-resources的测试类:
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class TryWithResources {
public static void main(String[] args) {
try (GZIPOutputStream gzip = new GZIPOutputStream(System.out)) {
gzip.write("TEST".getBytes("UTF-8"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
如何重写此类以使用try-catch-finally语句,这些语句产生与try-with-resources语句完全相同的字节码?此外,使用两个资源时的问题相同,如下例所示:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class TryWithResources2 {
public static void main(String[] args) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(baos)) {
gzip.write("TEST".getBytes("UTF-8"));
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
答案 0 :(得分:26)
对于TryWithResources
类,以下类生成与try-with-resources相同的字节码:
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class TryCatchFinally {
public static void main(String[] args) {
try {
final GZIPOutputStream gzip = new GZIPOutputStream(System.out);
Throwable gzipEx = null;
try {
gzip.write("TEST".getBytes("UTF-8"));
} catch (Throwable t) {
gzipEx = t;
throw t;
} finally {
if (gzip != null) {
if (gzipEx != null) {
try {
gzip.close();
} catch (Throwable t) {
gzipEx.addSuppressed(t);
}
} else {
gzip.close();
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
使用Sun JDK 1.7.0,TryWithResources
和TryCatchFinally
类中main方法的字节码和异常表为:
stack=3, locals=6, args_size=1
0: new #2 // class java/util/zip/GZIPOutputStream
3: dup
4: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
7: invokespecial #4 // Method java/util/zip/GZIPOutputStream."<init>":(Ljava/io/OutputStream;)V
10: astore_1
11: aconst_null
12: astore_2
13: aload_1
14: ldc #5 // String TEST
16: ldc #6 // String UTF-8
18: invokevirtual #7 // Method java/lang/String.getBytes:(Ljava/lang/String;)[B
21: invokevirtual #8 // Method java/util/zip/GZIPOutputStream.write:([B)V
24: aload_1
25: ifnull 95
28: aload_2
29: ifnull 48
32: aload_1
33: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V
36: goto 95
39: astore_3
40: aload_2
41: aload_3
42: invokevirtual #11 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
45: goto 95
48: aload_1
49: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V
52: goto 95
55: astore_3
56: aload_3
57: astore_2
58: aload_3
59: athrow
60: astore 4
62: aload_1
63: ifnull 92
66: aload_2
67: ifnull 88
70: aload_1
71: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V
74: goto 92
77: astore 5
79: aload_2
80: aload 5
82: invokevirtual #11 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
85: goto 92
88: aload_1
89: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V
92: aload 4
94: athrow
95: goto 103
98: astore_1
99: aload_1
100: invokevirtual #13 // Method java/io/IOException.printStackTrace:()V
103: return
Exception table:
from to target type
32 36 39 Class java/lang/Throwable
13 24 55 Class java/lang/Throwable
13 24 60 any
70 74 77 Class java/lang/Throwable
55 62 60 any
0 95 98 Class java/io/IOException
对于TryWithResources2
类,以下类生成与try-with-resources相同的字节码:
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
public class TryCatchFinally2 {
public static void main(String[] args) {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
Throwable baosEx = null;
try {
final GZIPOutputStream gzip = new GZIPOutputStream(baos);
Throwable gzipEx = null;
try {
gzip.write("TEST".getBytes("UTF-8"));
} catch (Throwable t) {
gzipEx = t;
throw t;
} finally {
if (gzip != null) {
if (gzipEx != null) {
try {
gzip.close();
} catch (Throwable t) {
gzipEx.addSuppressed(t);
}
} else {
gzip.close();
}
}
}
} catch (Throwable t) {
baosEx = t;
throw t;
} finally {
if (baos != null) {
if (baosEx != null) {
try {
baos.close();
} catch (Throwable t) {
baosEx.addSuppressed(t);
}
} else {
baos.close();
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
TryWithResources2
和TryCatchFinally2
类中main方法的字节码和异常表是:
stack=3, locals=10, args_size=1
0: new #2 // class java/io/ByteArrayOutputStream
3: dup
4: invokespecial #3 // Method java/io/ByteArrayOutputStream."<init>":()V
7: astore_1
8: aconst_null
9: astore_2
10: new #4 // class java/util/zip/GZIPOutputStream
13: dup
14: aload_1
15: invokespecial #5 // Method java/util/zip/GZIPOutputStream."<init>":(Ljava/io/OutputStream;)V
18: astore_3
19: aconst_null
20: astore 4
22: aload_3
23: ldc #6 // String TEST
25: ldc #7 // String UTF-8
27: invokevirtual #8 // Method java/lang/String.getBytes:(Ljava/lang/String;)[B
30: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.write:([B)V
33: aload_3
34: ifnull 114
37: aload 4
39: ifnull 61
42: aload_3
43: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V
46: goto 114
49: astore 5
51: aload 4
53: aload 5
55: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
58: goto 114
61: aload_3
62: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V
65: goto 114
68: astore 5
70: aload 5
72: astore 4
74: aload 5
76: athrow
77: astore 6
79: aload_3
80: ifnull 111
83: aload 4
85: ifnull 107
88: aload_3
89: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V
92: goto 111
95: astore 7
97: aload 4
99: aload 7
101: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
104: goto 111
107: aload_3
108: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V
111: aload 6
113: athrow
114: aload_1
115: ifnull 185
118: aload_2
119: ifnull 138
122: aload_1
123: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V
126: goto 185
129: astore_3
130: aload_2
131: aload_3
132: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
135: goto 185
138: aload_1
139: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V
142: goto 185
145: astore_3
146: aload_3
147: astore_2
148: aload_3
149: athrow
150: astore 8
152: aload_1
153: ifnull 182
156: aload_2
157: ifnull 178
160: aload_1
161: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V
164: goto 182
167: astore 9
169: aload_2
170: aload 9
172: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
175: goto 182
178: aload_1
179: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V
182: aload 8
184: athrow
185: goto 193
188: astore_1
189: aload_1
190: invokevirtual #15 // Method java/io/IOException.printStackTrace:()V
193: return
Exception table:
from to target type
42 46 49 Class java/lang/Throwable
22 33 68 Class java/lang/Throwable
22 33 77 any
88 92 95 Class java/lang/Throwable
68 79 77 any
122 126 129 Class java/lang/Throwable
10 114 145 Class java/lang/Throwable
10 114 150 any
160 164 167 Class java/lang/Throwable
145 152 150 any
0 185 188 Class java/io/IOException
答案 1 :(得分:23)
根据Java 7的Java语言规范(JLS)第14.20.3.1节:
try (VariableModifiersopt R Identifier = Expression ...)
Block
相当于
{
final VariableModifiers_minus_final R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
}
JLS涉及更多细节......在这里重现太多了。
关于try-with-resources的Java 7 JLS章节以HTML格式here提供,您可以获得JLS here的PDF版本。