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出现: not a git repository
使用用git add . 出现这样错误: fatal: not a git repository (or any of the parent directories): .git 意思是说:.git没 ...
- jconsole & jvisualvm远程监视websphere服务器JVM的配置案
jconsole是JDK里自带的一个工具,可以监测Java程序运行时所有对象的申请.释放等动作,将内存管理的所有信息进行统计.分析.可视化.我们可以根据这些信息判断程序是否有内存泄漏问题. 使用jco ...
- elasticSearch聚合sum查询
有时需要统计一段时间内,订单的总金额.类似于sql的sum,针对某一字段求和.这就涉及到es的聚合查询,来看看用spring-data-elasticSearch怎么写: QueryBuilder ...
- CodeIgniter框架通过URL向控制器传递参数
通过URL传递参数的方法是GET,在CodeIgnter框架中,通过URL有两种方式向控制器传递参数: 一种是键值对的形式. 一种是类似于文件路径的形式,这个时候,不是以键值对的形式了,我们只传递值. ...
- Nginx Configuring HTTPS servers
Configuring HTTPS servershttp://nginx.org/en/docs/http/configuring_https_servers.html Configuring HT ...
- Python3练习题求1000以内所有3和5的倍数的总和
sum = 0 for i in range(1,1000): if i%3 == 0 or i%5 == 0: sum += i print(sum)
- 2 Servlet 细节
1 Servlet 配置详解 ① 由于客户端在浏览器只能通过URL访问web服务器的资源,所以Servlet程序若想被外界访问,必须把Servlet 程序映射到一个URL 地址上,这个工作在项目we ...
- 为什么说Java中只有值传递(转载)
出处:https://www.hollischuang.com/archives/2275 关于这个问题,在StackOverflow上也引发过广泛的讨论,看来很多程序员对于这个问题的理解都不尽相同, ...
- [转帖]xargs命令详解,xargs与管道的区别
xargs命令详解,xargs与管道的区别 https://www.cnblogs.com/wangqiguo/p/6464234.html 之前一直说要学习一下 xargs 到现在为止也没学习.. ...
- Day 5-4封装.__隐藏属性或者方法
封装 property 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 在python中用双下划线开头的方式将属性隐藏起来(设置成 ...