Java代码如下所示:
File f1 = File.createTempFile("example", ".txt");
File f2 = File.createTempFile("outExample", ".txt");
FileInputStream in = new FileInputStream(f1);
FileOutputStream out = new FileOutputStream(f2);
try {
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}
finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
return f1.delete() && f2.delete();
和字节码:
TRYCATCHBLOCK L0 L1 L1
L2
LINENUMBER 138 L2
LDC "example"
LDC ".txt"
INVOKESTATIC File.createTempFile (String, String) : File
ASTORE 1
L3
LINENUMBER 139 L3
LDC "outExample"
LDC ".txt"
INVOKESTATIC File.createTempFile (String, String) : File
ASTORE 2
L4
LINENUMBER 141 L4
NEW FileInputStream
DUP
ALOAD 1: f1
INVOKESPECIAL FileInputStream.<init> (File) : void
ASTORE 3
L5
LINENUMBER 142 L5
NEW FileOutputStream
DUP
ALOAD 2: f2
INVOKESPECIAL FileOutputStream.<init> (File) : void
ASTORE 4
L0
LINENUMBER 146 L0
GOTO L6
L7
LINENUMBER 147 L7
ALOAD 4: out
ILOAD 5: c
INVOKEVIRTUAL FileOutputStream.write (int) : void
L6
LINENUMBER 146 L6
ALOAD 3: in
INVOKEVIRTUAL FileInputStream.read () : int
DUP
ISTORE 5
L8
ICONST_M1
IF_ICMPNE L7
L9
LINENUMBER 149 L9
GOTO L10
L1
LINENUMBER 150 L1
ASTORE 6
L11
LINENUMBER 151 L11
ALOAD 3: in
IFNULL L12
L13
LINENUMBER 152 L13
ALOAD 3: in
INVOKEVIRTUAL FileInputStream.close () : void
L12
LINENUMBER 154 L12
ALOAD 4: out
IFNULL L14
L15
LINENUMBER 155 L15
ALOAD 4: out
INVOKEVIRTUAL FileOutputStream.close () : void
L14
LINENUMBER 157 L14
ALOAD 6
ATHROW
L10
LINENUMBER 151 L10
ALOAD 3: in
IFNULL L16
L17
LINENUMBER 152 L17
ALOAD 3: in
INVOKEVIRTUAL FileInputStream.close () : void
L16
LINENUMBER 154 L16
ALOAD 4: out
IFNULL L18
L19
LINENUMBER 155 L19
ALOAD 4: out
INVOKEVIRTUAL FileOutputStream.close () : void
L18
LINENUMBER 159 L18
ALOAD 1: f1
INVOKEVIRTUAL File.delete () : boolean
IFEQ L20
ALOAD 2: f2
INVOKEVIRTUAL File.delete () : boolean
IFEQ L20
ICONST_1
IRETURN
L20
ICONST_0
IRETURN
有人可以告诉我为什么每个流(L13和L17,L15和L19)调用两次close()指令?如果没有finally块,但是使用try-catch,在字节码中每个流只调用一个close()。
答案 0 :(得分:5)
Ones适用于隐式捕获异常且需要重新抛出的情况(请注意最后的ATHROW
)
L15
LINENUMBER 155 L15
ALOAD 4: out
INVOKEVIRTUAL FileOutputStream.close () : void
L14
LINENUMBER 157 L14
ALOAD 6
ATHROW
另一个没有抛出异常的时候:
L19
LINENUMBER 155 L19
ALOAD 4: out
INVOKEVIRTUAL FileOutputStream.close () : void
如果你看顶部,你会看到
TRYCATCHBLOCK L0 L1 L1
这些标签类似于在哪里跳跃捕获以及在哪里跳转到最后。 Catch将抛出的异常留在堆栈的顶部(同样,ATHROW)。检查堆栈以查看顶级成员是否是异常是比复制代码更昂贵(更难/不可能;堆栈没有打字)。