为了解决问题,偶然发现一个奇怪的地方:就是使用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;
}

最后也能反编译成功,但是反编译的文件有点看不懂了,反编译后部分截图:

try-with-resource机制的一个编译陷阱的更多相关文章

  1. 揭秘autoit3的运行机制和反编译原理

    今天发这个帖子的目的在于和论坛里面的朋友交流一下学习心得,主要内容是围绕着autoit3的编译原理.先开门见山的说一下结果,我不知道如何反编译au3,但相信论坛有很多高手,能解开我心中的疑团.我没有想 ...

  2. 如何编写一个编译c#控制台应用程序的批处理程序

    如何编写一个编译c#控制台应用程序的批处理程序 2011-03-22 18:14 dc毒蘑菇 | 浏览 579 次 最近在网上看了一个教程,是学C#的,但是我的机子上装不上vs,所以想写一个批处理来编 ...

  3. C#实现的内存分页机制的一个实例

    C#实现的内存分页机制的一个实例 //多页索引表管理类(全局主索引表管理类) public class MuliPageIndexFeatureClass : IDisposable { protec ...

  4. Java-Runoob-高级教程-实例-环境设置实例:2.Java 实例 – Java 如何运行一个编译过的类文件?

    ylbtech-Java-Runoob-高级教程-实例-环境设置实例:2.Java 实例 – Java 如何运行一个编译过的类文件? 1.返回顶部 1. Java 实例 - 如何执行编译过 Java ...

  5. 疯狂补贴的4G+  会是又一个资费陷阱吗?

     会是又一个资费陷阱吗?" title="疯狂补贴的4G+  会是又一个资费陷阱吗?"> 常言说得好,防火防盗防运营商--具有垄断性质的中国移动.联通.电信三大基础 ...

  6. 一个C++引用库的头文件预编译陷阱

    写在前面 老胡最近在工作中,有个场景需要使用一个第三方库,引用头文件,链接库,编译运行,一切都很正常,但是接下来就遇到了一个很诡异的问题,调用该库的中的一个对象方法为对象修改属性的时候,会影响到对象的 ...

  7. ClassLoader机制:一个类何时会被虚拟机初始化?

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 大家都知道Java程序被编译器编译成字节码文件保存在硬盘里,Java虚拟机在执行代码时首先要把编译后的字节码文件从硬盘加载到内存中,然后才 ...

  8. 二 Java利用等待/通知机制实现一个线程池

    接着上一篇博客的 一Java线程的等待/通知模型 ,没有看过的建议先看一下.下面我们用等待通知机制来实现一个线程池 线程的任务就以打印一行文本来模拟耗时的任务.主要代码如下: 1  定义一个任务的接口 ...

  9. java中DelayQueue的一个使用陷阱分析

    最近工作中有接触到DelayQueue,网上搜索资料的时候发现一篇文章谈到DelayQueue的坑.点击打开链接 文中已经总结了遇到坑的地方,还有解决方案.不过我第一眼看一下没弄明白为什么,所以翻了翻 ...

随机推荐

  1. Python中的鸡肋多线程

    作者:DarrenChan陈驰链接:https://www.zhihu.com/question/23474039/answer/269526476来源:知乎著作权归作者所有.商业转载请联系作者获得授 ...

  2. kuangbin 基础DP集合

    HDU 1024第一遍水过,没有体会到这个题的奥妙,思考了很久终于体会了.大概意思是求把序列分成m段的子序列,并不一定要覆盖完,求子序列和的最大值我们首先要写出基本的动态转移方程: DP:dp[ i ...

  3. Wannafly挑战赛28

    总结- A-开始觉得是找规律,最开始模拟当时我觉得如果L达到1e9的范围的话,岂不是要加1e9次,模拟也就没有认真写,现在想来,后面由于加的不再是1,而是我前面的值,这样相当了一个斐波那契的类型,而斐 ...

  4. Generalized Power Method for Sparse Principal Component Analysis

    目录 重点 算法 这篇文章,看的晕晕的,但是被引用了400多次了,就简单地记一笔. 这个东西,因为\(\ell_1\)范数,所以会稀疏化,当然,和\(\gamma\)有关. 重点 我想重点写的地方是下 ...

  5. react虚拟dom diff算法

    react虚拟dom:依据diff算法 前端:更新状态.更新视图:所以前端页面的性能问题主要是由Dom操作引起的,解放Dom操作复杂性 刻不容缓 因为:Dom渲染慢,而JS解析编译相对非常非常非常快! ...

  6. python知识点及面试面试大集合

    题目来源:武sir--一个很有意思的人,点击这儿跳转 一.基础篇 为什么学习Python? 通过什么途径学习的Python? Python和Java.PHP.C.C#.C++等其他语言的对比? 简述解 ...

  7. java web 常见异常及解决办法

    javax.servlet.ServletException: javax/servlet/jsp/SkipPageException 重启tomcat, javax.servlet.ServletE ...

  8. 【kindle笔记】之 《浪潮之巅》- 2018-1-

    <浪潮之巅> 这本书推荐自最爱的政治课老师. 政治课老师张巍老师.我会一直记得你的. 以这样的身份来到这个学校,他人的质疑,自己的忐忑,老板的不公.犹犹豫豫谨小慎微地前进. 第一次听到这样 ...

  9. C#复习笔记(4)--C#3:革新写代码的方式(扩展方法)

    扩展方法 扩展方法有以下几个需求: 你想为一个类型添加一些 成员: 你不需要为类型的实例添加任何更多的数据: 你不能改变类型本身, 因为是别人的代码. 对于C#1和C#2中的静态方法,扩展方法是一种更 ...

  10. [转帖]Windows NT 之父 - David Cutler

    Windows NT 之父 - David Cutler https://www.cnblogs.com/wangwust/p/6826200.html 曾经下过 夺路狂奔的电子书 但是还没看完.. ...