为了解决问题,偶然发现一个奇怪的地方:就是使用try-with-resource机制的代码编译后,使用jd-gui反编译文件出现// ERROR //,但是程序运行却是正常的。
进一步确认后发现:如果try语句中只有一个定义时,反编译后也不会报错(如果有两个可以嵌套try语句);而且编译完以后的代码跟正常的代码编译完后的差距很大。
以下是测试证明:
原始的写法举例
public byte[] file2byte(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
try {
fis = new FileInputStream(file);
bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
buffer = bos.toByteArray();
} catch (Exception e) {
// e.printStackTrace();
} finally{
try {
if(fis != null){
fis.close();
}
if(bos != null){
bos.close();
}
} catch (IOException e) {
//e.printStackTrace();
}
}
return buffer;
}
反编译结果:
public byte[] file2byte(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
FileInputStream fis = null;
ByteArrayOutputStream bos = null;
try {
fis = new FileInputStream(file);
bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
int n;
bos.write(b, 0, n);
}
buffer = bos.toByteArray();
}
catch (Exception localException)
{
try {
if (fis != null) {
fis.close();
}
if (bos != null)
bos.close();
}
catch (IOException localIOException)
{
}
}
finally
{
try
{
if (fis != null) {
fis.close();
}
if (bos != null)
bos.close();
}
catch (IOException localIOException1)
{
}
}
return buffer;
}
反编译后部分截图:
try语句中有两个定义的时候
public byte[] file2byte(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
buffer = bos.toByteArray();
} catch (Exception e) {
// e.printStackTrace();
}
return buffer;
}
反编译结果:
// ERROR //
public byte[] file2byte(String filePath)
{
// Byte code:
// 0: aconst_null
// 1: astore_2
// 2: new 725 java/io/File
// 5: dup
// 6: aload_1
// 7: invokespecial 727 java/io/File:<init> (Ljava/lang/String;)V
// 10: astore_3
// 11: aconst_null
// 12: astore 4
// 14: aconst_null
// 15: astore 5
// 17: new 728 java/io/FileInputStream
// 20: dup
// 21: aload_3
// 22: invokespecial 730 java/io/FileInputStream:<init> (Ljava/io/File;)V
// 25: astore 6
// 27: new 733 java/io/ByteArrayOutputStream
// 30: dup
// 31: invokespecial 735 java/io/ByteArrayOutputStream:<init> ()V
// 34: astore 7
// 36: ldc_w 736
// 39: newarray byte
// 41: astore 8
// 43: goto +13 -> 56
// 46: aload 7
// 48: aload 8
// 50: iconst_0
// 51: iload 9
// 53: invokevirtual 737 java/io/ByteArrayOutputStream:write ([BII)V
// 56: aload 6
// 58: aload 8
// 60: invokevirtual 740 java/io/FileInputStream:read ([B)I
// 63: dup
// 64: istore 9
// 66: iconst_m1
// 67: if_icmpne -21 -> 46
// 70: aload 7
// 72: invokevirtual 744 java/io/ByteArrayOutputStream:toByteArray ()[B
// 75: astore_2
// 76: aload 7
// 78: ifnull +26 -> 104
// 81: aload 7
// 83: invokevirtual 748 java/io/ByteArrayOutputStream:close ()V
// 86: goto +18 -> 104
// 89: astore 4
// 91: aload 7
// 93: ifnull +8 -> 101
// 96: aload 7
// 98: invokevirtual 748 java/io/ByteArrayOutputStream:close ()V
// 101: aload 4
// 103: athrow
// 104: aload 6
// 106: ifnull +85 -> 191
// 109: aload 6
// 111: invokevirtual 749 java/io/FileInputStream:close ()V
// 114: goto +77 -> 191
// 117: astore 5
// 119: aload 4
// 121: ifnonnull +10 -> 131
// 124: aload 5
// 126: astore 4
// 128: goto +17 -> 145
// 131: aload 4
// 133: aload 5
// 135: if_acmpeq +10 -> 145
// 138: aload 4
// 140: aload 5
// 142: invokevirtual 700 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V
// 145: aload 6
// 147: ifnull +8 -> 155
// 150: aload 6
// 152: invokevirtual 749 java/io/FileInputStream:close ()V
// 155: aload 4
// 157: athrow
// 158: astore 5
// 160: aload 4
// 162: ifnonnull +10 -> 172
// 165: aload 5
// 167: astore 4
// 169: goto +17 -> 186
// 172: aload 4
// 174: aload 5
// 176: if_acmpeq +10 -> 186
// 179: aload 4
// 181: aload 5
// 183: invokevirtual 700 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V
// 186: aload 4
// 188: athrow
// 189: astore 4
// 191: aload_2
// 192: areturn
//
// Exception table:
// from to target type
// 36 76 89 finally
// 27 104 117 finally
// 17 158 158 finally
// 11 189 189 java/lang/Exception
}
反编译后部分截图:
每个try语句中有只有一个定义的时候
public byte[] file2byte(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
try(FileInputStream fis = new FileInputStream(file);) {
try(ByteArrayOutputStream bos = new ByteArrayOutputStream();){
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
buffer = bos.toByteArray();
}
} catch (Exception e) {
// e.printStackTrace();
}
return buffer;
}
反编译结果:
public byte[] file2byte(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
try { Object localObject1 = null; Object localObject4 = null;
Object localObject3;
label197:
try { fis = new FileInputStream(file);
}
finally
{
FileInputStream fis;
Object localObject5;
Object localObject8;
ByteArrayOutputStream bos;
byte[] b;
int n;
int n;
Object localObject7;
localObject3 = localThrowable1; break label197; if (localObject3 != localThrowable1) localObject3.addSuppressed(localThrowable1);
}
} catch (Exception localException1) {
}
return buffer;
}
最后也能反编译成功,但是反编译的文件有点看不懂了,反编译后部分截图: