try-with-resource机制的一个编译陷阱
为了解决问题,偶然发现一个奇怪的地方:就是使用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机制的一个编译陷阱的更多相关文章
- 揭秘autoit3的运行机制和反编译原理
今天发这个帖子的目的在于和论坛里面的朋友交流一下学习心得,主要内容是围绕着autoit3的编译原理.先开门见山的说一下结果,我不知道如何反编译au3,但相信论坛有很多高手,能解开我心中的疑团.我没有想 ...
- 如何编写一个编译c#控制台应用程序的批处理程序
如何编写一个编译c#控制台应用程序的批处理程序 2011-03-22 18:14 dc毒蘑菇 | 浏览 579 次 最近在网上看了一个教程,是学C#的,但是我的机子上装不上vs,所以想写一个批处理来编 ...
- C#实现的内存分页机制的一个实例
C#实现的内存分页机制的一个实例 //多页索引表管理类(全局主索引表管理类) public class MuliPageIndexFeatureClass : IDisposable { protec ...
- Java-Runoob-高级教程-实例-环境设置实例:2.Java 实例 – Java 如何运行一个编译过的类文件?
ylbtech-Java-Runoob-高级教程-实例-环境设置实例:2.Java 实例 – Java 如何运行一个编译过的类文件? 1.返回顶部 1. Java 实例 - 如何执行编译过 Java ...
- 疯狂补贴的4G+ 会是又一个资费陷阱吗?
会是又一个资费陷阱吗?" title="疯狂补贴的4G+ 会是又一个资费陷阱吗?"> 常言说得好,防火防盗防运营商--具有垄断性质的中国移动.联通.电信三大基础 ...
- 一个C++引用库的头文件预编译陷阱
写在前面 老胡最近在工作中,有个场景需要使用一个第三方库,引用头文件,链接库,编译运行,一切都很正常,但是接下来就遇到了一个很诡异的问题,调用该库的中的一个对象方法为对象修改属性的时候,会影响到对象的 ...
- ClassLoader机制:一个类何时会被虚拟机初始化?
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 大家都知道Java程序被编译器编译成字节码文件保存在硬盘里,Java虚拟机在执行代码时首先要把编译后的字节码文件从硬盘加载到内存中,然后才 ...
- 二 Java利用等待/通知机制实现一个线程池
接着上一篇博客的 一Java线程的等待/通知模型 ,没有看过的建议先看一下.下面我们用等待通知机制来实现一个线程池 线程的任务就以打印一行文本来模拟耗时的任务.主要代码如下: 1 定义一个任务的接口 ...
- java中DelayQueue的一个使用陷阱分析
最近工作中有接触到DelayQueue,网上搜索资料的时候发现一篇文章谈到DelayQueue的坑.点击打开链接 文中已经总结了遇到坑的地方,还有解决方案.不过我第一眼看一下没弄明白为什么,所以翻了翻 ...
随机推荐
- 使用git将项目上传到github
使用git将项目上传到github(最简单方法) 首先你需要一个github账号,所有还没有的话先去注册吧! https://github.com/ 我们使用git需要先安装git工具,这里给出下 ...
- rabbitmq集群运维一点总结
说明:以下操作都以三节点集群为例,机器名标记为机器A.机器B.机器C,如果为双节点忽略机器C,如果为各多节点则与机器C操作相同 一.rabbitmq集群必要条件 1.1.绑定实体ip,即ip a所能查 ...
- 把玩Alpine linux(二):APK包管理器
导读 Alpine Linux非常精简,开机内存占用也在二三十兆大,没有拆箱即用,就需要我们自己去做一些了解和配置 Alpine Linux的优劣 优势 Alpine Linux的Docker镜像特点 ...
- Glad to see you! CodeForces - 810D (交互+二分)
This is an interactive problem. In the output section below you will see the information about flush ...
- pandas数据清洗策略1
Pandas常用的数据清洗5大策略如下: 1.删除 DataFrame 中的不必要 columns 2.改变 DataFrame 的 index 3.使用 .str() 方法来清洗 columns 4 ...
- Day13 Python基础之time/datetime/random模块一(十一)
time模块 import time print(help(time)) time.time() #return current time in seconds since the Epoch as ...
- [2017BUAA软工助教]个人项目小结
2017BUAA个人项目小结 一.作业链接 http://www.cnblogs.com/jiel/p/7545780.html 二.评分细则 0.注意事项 按时间完成并提交--正常评分 晚交一周以内 ...
- HDU 3947 Assign the task
http://acm.hdu.edu.cn/showproblem.php?pid=3974 Problem Description There is a company that has N emp ...
- C# 和 c++的语法不同点
GC Garbage Collection 垃圾回收器 自动释放资源 关键字: new 1.创建对象 2.隐藏从父类继承的同名函数 using 1.引用命名空间 2. using(FileStrea ...
- 关于PHP批量图片格式转换的问题--本文转成webp, 其他过程格式一样
最近要把项目中的图片全部生成webp格式, 过程整理一下, (直接存在本地,或者图片链接存在数据库都可以看看) 首先,肯定是批量处理, 一个php处理不了这么多, 会爆内存的, 个人建议用aja ...