- 浏览: 408612 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (255)
- Android (53)
- java (57)
- javascript (7)
- linux (19)
- springside3 (6)
- spring (2)
- struts2 (11)
- hibernate (2)
- jsp&servlet (15)
- jquery (1)
- ExtJs (5)
- freemarker (1)
- apache (5)
- mysql (3)
- tomcat (3)
- eclipse&maven (23)
- 电脑小技巧 (1)
- 配置安装 (3)
- 开源框架 (2)
- 设计模式 (2)
- 架构 (2)
- ajax (1)
- 正则表达式 (7)
- 测试 (2)
- 装修 (1)
- 不错的软件 (4)
- http协议 (2)
- 网络 (2)
- windows (2)
- nodejs (1)
最新评论
-
yhyx:
好
JAVA URI URL区别 -
dingbuoyi:
我文章很早以前写的啊 估计软件版本早更新了 你要自己研究一下
windows下Sublime Text 2开发 Nodejs -
di1984HIT:
写的很好,学习了
【转帖】IP网段的计算和划分 -
农民柏柏:
感谢分享
【转】Android实现人人网点击“+”弹出效果 -
lianwanf:
大神,求源码,很想要那jar包.官方的不懂下载啊.谢谢啊. ...
开源框架ignition[二]
原帖地址:http://blog.csdn.net/BU_BetterYou/archive/2008/06/19/2564105.aspx
实践中的Java字节码
对Java字节码有了一定了解之后,我们可以来看看一些常用的和熟悉的Java语言的内容是如何与字节码映射的,也可以获得一些Java实现的细节内容。
Java 5:自动封装(autoboxing)
Java 5版本的一个新特性是自动封装(autoboxing),基础数据类型因语义环境的需要能转换成为对象类型,例如:
public class Autoboxing
{
public static void main(String[] args)
{
int x = 5;
java.util.ArrayList al = new java.util.ArrayList();
al.add(x);
}
}
在Java 5之前,这样的写法是错误的,因为x并不是对象。在Java 5下,编译后的字节码如下:
0: iconst_5
1: istore_1
2: new #2; //class java/util/ArrayList
5: dup
6: invokespecial #3; //Method java/util/ArrayList."<init>":()V
9: astore_2
10: aload_2
11: iload_1
12: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
15: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
18: pop
19: return
编号为0的行将整数常量5推送至堆栈,编号为1的行将堆栈顶端的5存储至第一个本地分片中。接下来,有四个操作符指令,new/dup/invokespecial/astore,是通常用来新创建对象并存储在本地变量中的做法。接下来,在编号为10的行,将ArrayList的引用推送至队战,然后再将x本地的值推送至堆栈。编号为12的行我们看到Java调用了静态的Integer.valueOf方法,它需要一个单独的堆栈分片,并消费整数值5,然后将包含着5的Integer对象推送到位。然后,这个对象就成为了add方法的参数,调用add方法就消费了Integer和ArrayList的引用,并将add方法的返回值推送回堆栈。
内部类(Inner Class)
在JDK 1.1发布时,Sun引入了内部类,支持创建与外部类有着特殊的私有可见关系的嵌套类。JVM并未引入像C++那样的friend功能,这就有点让Java使用者有个疑惑:在JVM本身强迫私有访问性时,而且把内部类看作跟其他类一样,Java如何对类的访问进行授权?
在下面这个例子中,内部类显然可以访问外部类的data私有属性:
class Outer
{
private int data = 12;
public Inner getInner()
{
return new Inner();
}
public class Inner
{
public int getData()
{
return data;
}
}
}
public class NestedFun
{
public static void main(String[] args)
{
Outer o = new Outer();
Outer.Inner i = o.getInner();
System.out.println(i.getData());
// prints 12; how?
}
}
对于这段代码,编译器如何进行工作呢?我们从NestedFun.main(String[])开始看字节码:
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=3, Args_size=1
0: new #2; //class Outer
3: dup
4: invokespecial #3; //Method Outer."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4; //Method Outer.getInner:()LOuter$Inner;
12: astore_2
13: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_2
17: invokevirtual #6; //Method Outer$Inner.getData:()I
20: invokevirtual #7; //Method java/io/PrintStream.println:(I)V
23: return
这段字节码还是比较直接的:Java使用了常用的new/dup/invokespecial/astore组合来创建Outer的实例,对Outer.getInner()和getData()的调用,其中对getData()调用的返回值直接传入了println()方法(注意,编译器选择先获取System.out,然后再是getData(),所以才能保证执行堆栈的位置顺序正确)。这一段基本没啥,我们再来看Outer.Inner.getDate()方法:
public class Outer$Inner extends java.lang.Object
SourceFile: "NestedFun.java"
InnerClass:
public #21= #4 of #18; //Inner=class Outer$Inner of class Outer
minor version: 0
major version: 50
Constant pool: (snipped)
{
final Outer this$0;
public Outer$Inner(Outer);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:LOuter;
5: aload_0
6: invokespecial #2; //Method java/lang/Object."<init>":()V
9: return
public int getData();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #1; //Field this$0:LOuter;
4: invokestatic #3; //Method Outer.access$000:(LOuter;)I
7: ireturn
}
这是去掉了一些输出后的结果,以便阅读。首先,我们看到了在Java规范中的“outer this”引用被显式加入内部类中作为一个属性,名为“this$0”,并标记为final。其次,编译器也生成了内部类的构造函数,用一个外部类的引用为“outer this”赋值,所以我们可以假定在外部类的getInner()方法中的new Inner()会用到本构造函数。第三,在内部类的getData()方法上,访问了一个外部类的静态方法叫“access$000”,来获取数据。
紧接着,我们可以看看外部类。
class Outer extends java.lang.Object{
private int data;
Outer();
Code:
0: aload_0
1: invokespecial #2; //Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 12
7: putfield #1; //Field data:I
10: return
public Outer$Inner getInner();
Code:
0: new #3; //class Outer$Inner
3: dup
4: aload_0
5: invokespecial #4; //Method Outer$Inner."<init>":(LOuter;)V
8: areturn
static int access$000(Outer);
Code:
0: aload_0
1: getfield #1; //Field data:I
4: ireturn
}
我们可以看见编译器生成了一个静态方法专为访问data开了个口子,不过“access$000”是包内私有的,也就是说在同包内的类才能访问该方法。
Java字节码工具
Java字节码功能工具很多,包括:
* Javassist
* Jasmin
* ……
也许,最重要的拆解字节码的工具还是javap。
实践中的Java字节码
对Java字节码有了一定了解之后,我们可以来看看一些常用的和熟悉的Java语言的内容是如何与字节码映射的,也可以获得一些Java实现的细节内容。
Java 5:自动封装(autoboxing)
Java 5版本的一个新特性是自动封装(autoboxing),基础数据类型因语义环境的需要能转换成为对象类型,例如:
public class Autoboxing
{
public static void main(String[] args)
{
int x = 5;
java.util.ArrayList al = new java.util.ArrayList();
al.add(x);
}
}
在Java 5之前,这样的写法是错误的,因为x并不是对象。在Java 5下,编译后的字节码如下:
0: iconst_5
1: istore_1
2: new #2; //class java/util/ArrayList
5: dup
6: invokespecial #3; //Method java/util/ArrayList."<init>":()V
9: astore_2
10: aload_2
11: iload_1
12: invokestatic #4; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
15: invokevirtual #5; //Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
18: pop
19: return
编号为0的行将整数常量5推送至堆栈,编号为1的行将堆栈顶端的5存储至第一个本地分片中。接下来,有四个操作符指令,new/dup/invokespecial/astore,是通常用来新创建对象并存储在本地变量中的做法。接下来,在编号为10的行,将ArrayList的引用推送至队战,然后再将x本地的值推送至堆栈。编号为12的行我们看到Java调用了静态的Integer.valueOf方法,它需要一个单独的堆栈分片,并消费整数值5,然后将包含着5的Integer对象推送到位。然后,这个对象就成为了add方法的参数,调用add方法就消费了Integer和ArrayList的引用,并将add方法的返回值推送回堆栈。
内部类(Inner Class)
在JDK 1.1发布时,Sun引入了内部类,支持创建与外部类有着特殊的私有可见关系的嵌套类。JVM并未引入像C++那样的friend功能,这就有点让Java使用者有个疑惑:在JVM本身强迫私有访问性时,而且把内部类看作跟其他类一样,Java如何对类的访问进行授权?
在下面这个例子中,内部类显然可以访问外部类的data私有属性:
class Outer
{
private int data = 12;
public Inner getInner()
{
return new Inner();
}
public class Inner
{
public int getData()
{
return data;
}
}
}
public class NestedFun
{
public static void main(String[] args)
{
Outer o = new Outer();
Outer.Inner i = o.getInner();
System.out.println(i.getData());
// prints 12; how?
}
}
对于这段代码,编译器如何进行工作呢?我们从NestedFun.main(String[])开始看字节码:
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=3, Args_size=1
0: new #2; //class Outer
3: dup
4: invokespecial #3; //Method Outer."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4; //Method Outer.getInner:()LOuter$Inner;
12: astore_2
13: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_2
17: invokevirtual #6; //Method Outer$Inner.getData:()I
20: invokevirtual #7; //Method java/io/PrintStream.println:(I)V
23: return
这段字节码还是比较直接的:Java使用了常用的new/dup/invokespecial/astore组合来创建Outer的实例,对Outer.getInner()和getData()的调用,其中对getData()调用的返回值直接传入了println()方法(注意,编译器选择先获取System.out,然后再是getData(),所以才能保证执行堆栈的位置顺序正确)。这一段基本没啥,我们再来看Outer.Inner.getDate()方法:
public class Outer$Inner extends java.lang.Object
SourceFile: "NestedFun.java"
InnerClass:
public #21= #4 of #18; //Inner=class Outer$Inner of class Outer
minor version: 0
major version: 50
Constant pool: (snipped)
{
final Outer this$0;
public Outer$Inner(Outer);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:LOuter;
5: aload_0
6: invokespecial #2; //Method java/lang/Object."<init>":()V
9: return
public int getData();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: getfield #1; //Field this$0:LOuter;
4: invokestatic #3; //Method Outer.access$000:(LOuter;)I
7: ireturn
}
这是去掉了一些输出后的结果,以便阅读。首先,我们看到了在Java规范中的“outer this”引用被显式加入内部类中作为一个属性,名为“this$0”,并标记为final。其次,编译器也生成了内部类的构造函数,用一个外部类的引用为“outer this”赋值,所以我们可以假定在外部类的getInner()方法中的new Inner()会用到本构造函数。第三,在内部类的getData()方法上,访问了一个外部类的静态方法叫“access$000”,来获取数据。
紧接着,我们可以看看外部类。
class Outer extends java.lang.Object{
private int data;
Outer();
Code:
0: aload_0
1: invokespecial #2; //Method java/lang/Object."<init>":()V
4: aload_0
5: bipush 12
7: putfield #1; //Field data:I
10: return
public Outer$Inner getInner();
Code:
0: new #3; //class Outer$Inner
3: dup
4: aload_0
5: invokespecial #4; //Method Outer$Inner."<init>":(LOuter;)V
8: areturn
static int access$000(Outer);
Code:
0: aload_0
1: getfield #1; //Field data:I
4: ireturn
}
我们可以看见编译器生成了一个静态方法专为访问data开了个口子,不过“access$000”是包内私有的,也就是说在同包内的类才能访问该方法。
Java字节码工具
Java字节码功能工具很多,包括:
* Javassist
* Jasmin
* ……
也许,最重要的拆解字节码的工具还是javap。
发表评论
-
JAVA中的Observable
2012-06-24 16:51 14071 addObserver deleteObserver都是同 ... -
为什么覆盖了equals方法一定要覆盖hashcode方法?
2012-06-08 11:14 12501 测试代码 public class HashMapTe ... -
java synchronized
2012-03-21 11:30 452我的理解,不一定正确的,如果有错误欢迎留言纠正 1 pub ... -
特殊字符与UNICODE码
2011-08-10 17:27 1697Unicode(统一码、万国码、单一码、标准万国码)是计算机科 ... -
【转】如何用ResourceBundle来读取配置文件 .
2011-08-10 16:47 813引用 对于ja va基础很好的人来说,这个应该是简单的不能再简 ... -
嵌入式JVM
2011-02-22 10:22 1315Robert Lougher发布了嵌入式JVM比较结果。他在嵌 ... -
CLASSPATH PATH 解释
2011-02-11 17:01 731ava执行环境本身就是一个平台,执行于这个平台上的程序是已编译 ... -
【转帖】java verbose命令
2011-02-11 17:01 801java -verbose[:class|gc|jni] ... -
JAVA嵌入式开发
2011-02-11 15:07 1046JVM选用 JAMVM http://jamvm.source ... -
JAVA 编译 解释 运行
2011-02-11 10:19 1310java是混合型语言。 先通过JAVA编译器把.java文件编 ... -
【转帖】类分解器JavaP--分析Java字节码
2011-02-11 09:38 1150原帖地址:http://www.comprg.com.cn/d ... -
【转帖】Java字节码揭秘(三)
2011-02-11 09:35 741原帖地址:http://blog.csdn.net/BU_Be ... -
【转帖】Java字节码揭秘(二)
2011-02-11 09:34 762原帖地址:http://blog.csdn.net/BU_Be ... -
【转帖】Java字节码揭秘(一)
2011-02-11 09:33 789原帖地址:http://blog.csdn.net/BU_Be ... -
JAVA volatile 关键字
2011-01-19 16:30 737每次读这个变量仍然要老老实实从内存读取,每次写这个变量也仍然要 ... -
java 排序
2011-01-11 15:47 9691 对象自然排序 第一种方式 排序对象必须实现Comparab ... -
JAVA 静态变量
2011-01-06 10:52 1214个人的总结 1 静态变量只有一份被类的所有实例共享 2 静态变 ... -
java 正则表达式
2011-01-05 17:18 404http://topic.csdn.net/u/2008082 ... -
java 注解
2011-01-05 10:20 360http://www.iteye.com/topic/4000 ... -
java jce provider
2011-01-04 17:41 7491 http://www.bouncycastle.org/
相关推荐
经典---JAVA设计模式经典---JAVA设计模式
简介:本系列的前一篇文章讨论了智能卡的相关知识,此篇文章则将着重介绍 JAVA 卡的一些基础知识,如 JAVA 卡的概念、结构和生命期,JAVA 卡的 JAVA 语言和编程接口(API),并通过一个简单的Applet示例引入对 JAVA卡...
论坛转帖工具 .......... 纯HTML
一键转帖 一键8经验签到. 绿易贴吧工具3.7 11.11版.rar
编辑人员转帖去水印工具,很好用,直接选中水印区域后运行伪装即可!
转帖性能测试
UBB论坛转帖圣手.exeUBB论坛转帖圣手.exe
J2ME全方位开发讲解基础汇总[转帖] 一、J2ME中需要的Java基础知识 现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成...
1.修改自Convert X转帖工具 2.新增批量替换关键词(原来是单个词语替换,可以利用这个...5.新增按颜色屏蔽干扰码 6.新增减少缩进以及优化了首行缩进 7.优化一些小细节 8.重新布局优化显示及方便操作 9.不断更新中...
discuz X2转帖工具、采集工具,discuz论坛批量发帖,批量转帖工具
这是一个世界编程大赛第一名写的程序,很好玩的,大家试试看。
Html2UBBMaxcj_Softii论坛专用转帖工具
转帖图片提取工具可以对论坛图片附件信息进行清除,只保留图片代码,操作很简单,推荐有需要转帖图片工具的朋友下载 转帖图片提取工具使用方法: 将IP138上处理过的东西复制到上方的编辑框内,点击只要图片,下面...
gl8雨刮维修以及调试转帖.doc
转帖PLCDCSFCS三大控制系统的特点和差异.doc
关于工作与生活的转帖 一篇论述精辟的文章,值得一看。
用PHP批量生成图片缩略图——活跃论坛转帖
看到论坛里帖子由精美的图片想转过来,或者批量提取地址时很好用
轻松转帖之突破网页复制限制宣贯.pdf