您的位置:首页 > 编程语言 > Java开发

使用javap分析finally块和return值

2011-04-22 17:06 176 查看
使用javap分析finally块和return

标题: 使用javap分析finally块中return值
作者: pwsource
邮箱: pwsource@gmail.com

目录:
1.使用javap反编译字节码分析原因。 啥也甭说,看源码注释
2. 源代码

正文:

1. 使用javap反编译字节码分析原因。

E:/>javap -c -classpath E:/workspace/myTest/bin test.Test
E:/>javap -c -classpath E:/workspace/myTest/bin test.Test
Compiled from "Test.java"
public class test.Test extends java.lang.Object{
public test.Test();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return

public static int testInt();
Code:
0: iconst_0
1: istore_0 //x=0 ,保存在本地变量store[0]中
2: iconst_1
3: istore_0 //x=1
4: iload_0 //获取store[0](x=1)的值
5: istore_3 // 将store[0](x=1) 转存在本地变量store[3]中
6: jsr 17 // 跳转到finally块
9: iload_3 // 获取store[3]的值x=1
10: ireturn //返回x=1
11: astore_2
12: jsr 17
15: aload_2
16: athrow
17: astore_1 //finally块
18: iconst_2 //相对于testRef()此处不需要再次load变量,因为code:4 已将数据加载到栈顶了。
19: istore_0 //对x赋值2,将x的值保存在本地变量store[0]中
20: ret 1 //返回到代码【6: jsr 17】
Exception table:
from to target type
2 9 11 any

public static test.Test$Ref testRef();
Code:
0: new #20; //class test/Test$Ref //创建Ref实例
3: dup //拷贝Ref实例到栈顶
4: aconst_null
5: invokespecial #22; //Method test/Test$Ref."<init>":(Ltest/Test$Ref;)V //初始化 Ref.x=null
8: astore_0 //将Ref实例的引用ref保存在 store[0]
9: aload_0
10: iconst_1
11: invokestatic #25; //Method test/Test$Ref.access$1:(Ltest/Test$Ref;I)V //赋值Ref.x=1
14: aload_0 // 从store[0]加载Ref实例的引用ref
15: astore_3 // 保存Ref实例的引用ref到store[3]
16: jsr 27 // jump to finally 块
19: aload_3 // store[3]中加载Ref实例的引用ref,实例的值ref.x已经变为2
20: areturn // 返回Ref.x=2
21: astore_2
22: jsr 27
25: aload_2
26: athrow
27: astore_1 // finally块
28: aload_0 // 从store[0]加载Ref实例的应用
29: iconst_2
30: invokestatic #25; //Method test/Test$Ref.access$1:(Ltest/Test$Ref;I)V //通过实例的引用ref修改x的值, Ref.x=2

33: ret 1 //返回到代码【16: jsr 27】
Exception table:
from to target type
9 19 21 any

public static java.lang.String testArr();
Code:
0: iconst_1 //数组大小为1
1: anewarray #33; //class java/lang/String //创建数组对象
4: dup //复制数组的引用x到栈顶
5: iconst_0 //数组x的索引0
6: ldc #35; //String 0
8: aastore //将字符串”0”的引用存入数组x[0]的位置 。注意,数组保存的是对象的引用。
9: astore_0 //将数组的应用x保存在store[0]
10: aload_0 //从store[0]加载数组x的引用到栈顶
11: iconst_0 //数组x的索引0
12: ldc #37; //String 1
14: aastore //将字符串”1”的引用存入数组x[0]的位置
15: aload_0 //从store[0]加载数组x的引用到栈顶
16: iconst_0 //数组x的索引0
17: aaload //加载x[0],x[0]保存的是字符串”1”的索引
18: astore_3 //x[0]字符串”1”的索引)保存在store[3]
19: jsr 30 // jump to finally
22: aload_3 //store[3]加载x[0], x[0]=”1”
23: areturn // 返回x[0]=”1”
24: astore_2
25: jsr 30
28: aload_2
29: athrow
30: astore_1
31: aload_0 //从store[0]加载数组x的引用到栈顶
32: iconst_0 //数组x的索引0
33: ldc #39; //String 2
35: aastore //将字符串”2”的引用存入数组x[0]的位置
36: ret 1

Exception table:
from to target type
10 22 24 any

public static void main(java.lang.String[]);
Code:
0: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream;
3: new #50; //class java/lang/StringBuffer
6: dup
7: ldc #52; //String x=?
9: invokespecial #54; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
12: invokestatic #57; //Method testInt:()I
15: invokevirtual #59; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
18: invokevirtual #63; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
21: invokevirtual #66; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
24: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream;
27: new #50; //class java/lang/StringBuffer
30: dup
31: ldc #52; //String x=?
33: invokespecial #54; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
36: invokestatic #71; //Method testRef:()Ltest/Test$Ref;
39: invokevirtual #73; //Method java/lang/StringBuffer.append:(Ljava/lang/Object;)Ljava/lang/StringBuffer;
42: invokevirtual #63; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
45: invokevirtual #66; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
48: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream;
51: new #50; //class java/lang/StringBuffer
54: dup
55: ldc #52; //String x=?
57: invokespecial #54; //Method java/lang/StringBuffer."<init>":(Ljava/lang/String;)V
60: invokestatic #76; //Method testArr:()Ljava/lang/String;
63: invokevirtual #78; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
66: invokevirtual #63; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
69: invokevirtual #66; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
72: return
}

2. 源代码

public class Test
{

public static int testInt()
{
int x = 0;
try
{
x = 1;
return x;
}
finally
{
x = 2;
}
}

public static Ref testRef()
{
Ref ref = new Ref();
try
{
ref.x = 1;
return ref;
}
finally
{
ref.x = 2;
}
}

public static String testArr()
{
String[] x = { "0" };
try
{
x[0] = "1";
return x[0];
}
finally
{
x[0] = "2";
}
}

public static void main(String[] args)
{
System.out.println("x=? " + testInt());
System.out.println("x=? " + testRef());
System.out.println("x=? " + testArr());
}

private static class Ref
{
private int x;

public String toString()
{
return String.valueOf(x);
}

}
}


运行结果:
x=? 1
x=? 2
x=? 1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: