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的坑.点击打开链接 文中已经总结了遇到坑的地方,还有解决方案.不过我第一眼看一下没弄明白为什么,所以翻了翻 ...
随机推荐
- CRM系统设计方案
CRM系统设计方案 - 百度文库https://wenku.baidu.com/view/a34eebeb0242a8956bece473.html 服务支持http://www.uf-crm.com ...
- react双组件传值和传参
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- idea远程调试tomcat
在开发Spring Boot应用的时候,会发现有的时候在idea工具中运行程序和打包程序后在tomcat下运行程序的结果会不太一样,因此就需要远程调试tomcat. 首先在tomcat目录下的bin目 ...
- [转帖]整理:Windows系统下的奇技淫巧大汇总
整理:Windows系统下的奇技淫巧大汇总 https://blog.csdn.net/bat67/article/details/76381357 Win+home Crtl+home 还有 Win ...
- IWMS后台上传文章,嵌入音频文件代码
<object width="260" height="69" classid="clsid:6bf52a52-394a-11d3-b153-0 ...
- Scrapy网络爬虫框架的开发使用
1.安装 2.使用scrapy startproject project_name 命令创建scrapy项目 如图: 3.根据提示使用scrapy genspider spider_name dom ...
- ajax查看详细返回信息
查看详细成功返回信息: success : function(data, textStatus, jqXHR) { console.log(data); console.log(textStatus) ...
- 阿里云ECS服务器,CentOS 7.4配置jdk+tomcat+mysql
参考博客: https://mp.weixin.qq.com/s?__biz=MzIxMzk3Mjg5MQ==&mid=2247484020&idx=1&sn=6e0aa07f ...
- python time模块介绍(日期格式化 时间戳)
import time # 1.time.time() 用于获取当前时间的时间戳, ticks = time.time() print(ticks) # 1545617668.8195682 浮点数 ...
- scrapy 项目搭建
安装好scrapy后,开始创建项目 项目名:zhaopin 爬虫文件名:zhao 1:cmd -- scrapy startproject zhaopin 2:cd zhaopin,进入项目目 ...