- 浏览: 416735 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (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 14701 addObserver deleteObserver都是同 ... -
为什么覆盖了equals方法一定要覆盖hashcode方法?
2012-06-08 11:14 13101 测试代码 public class HashMapTe ... -
java synchronized
2012-03-21 11:30 480我的理解,不一定正确的,如果有错误欢迎留言纠正 1 pub ... -
特殊字符与UNICODE码
2011-08-10 17:27 1717Unicode(统一码、万国码、单一码、标准万国码)是计算机科 ... -
【转】如何用ResourceBundle来读取配置文件 .
2011-08-10 16:47 852引用 对于ja va基础很好的人来说,这个应该是简单的不能再简 ... -
嵌入式JVM
2011-02-22 10:22 1349Robert Lougher发布了嵌入式JVM比较结果。他在嵌 ... -
CLASSPATH PATH 解释
2011-02-11 17:01 766ava执行环境本身就是一个平台,执行于这个平台上的程序是已编译 ... -
【转帖】java verbose命令
2011-02-11 17:01 832java -verbose[:class|gc|jni] ... -
JAVA嵌入式开发
2011-02-11 15:07 1112JVM选用 JAMVM http://jamvm.source ... -
JAVA 编译 解释 运行
2011-02-11 10:19 1344java是混合型语言。 先通过JAVA编译器把.java文件编 ... -
【转帖】类分解器JavaP--分析Java字节码
2011-02-11 09:38 1181原帖地址:http://www.comprg.com.cn/d ... -
【转帖】Java字节码揭秘(三)
2011-02-11 09:35 762原帖地址:http://blog.csdn.net/BU_Be ... -
【转帖】Java字节码揭秘(二)
2011-02-11 09:34 792原帖地址:http://blog.csdn.net/BU_Be ... -
【转帖】Java字节码揭秘(一)
2011-02-11 09:33 820原帖地址:http://blog.csdn.net/BU_Be ... -
JAVA volatile 关键字
2011-01-19 16:30 758每次读这个变量仍然要老老实实从内存读取,每次写这个变量也仍然要 ... -
java 排序
2011-01-11 15:47 9941 对象自然排序 第一种方式 排序对象必须实现Comparab ... -
JAVA 静态变量
2011-01-06 10:52 1244个人的总结 1 静态变量只有一份被类的所有实例共享 2 静态变 ... -
java 正则表达式
2011-01-05 17:18 435http://topic.csdn.net/u/2008082 ... -
java 注解
2011-01-05 10:20 391http://www.iteye.com/topic/4000 ... -
java jce provider
2011-01-04 17:41 7821 http://www.bouncycastle.org/
相关推荐
《转帖经典---JAVA设计模式》这本书或资料可能涵盖了这些模式的详细解释、示例代码以及如何在实际项目中应用这些模式。通过学习和理解这些设计模式,开发者能够更好地设计和重构软件,提升代码质量。
标题中的“论坛转帖工具.rar”表明这是一个用于在论坛之间转移帖子的软件工具,通常用于帮助用户方便地将一个论坛的帖子内容复制到另一个论坛,可能是为了分享信息、讨论或保存重要的帖子。这类工具可能包括自动抓取...
UBB论坛转帖圣手.exeUBB论坛转帖圣手.exe
【贴吧转帖工具】是一种专为百度贴吧用户设计的便捷工具,主要用于提高用户在贴吧中的互动效率。通过这款工具,用户可以实现一键转帖和一键8经验签到的功能,极大地简化了传统操作流程,节省了用户的时间,提升了...
本篇文章将详细探讨“编辑人员转帖去水印工具”,并介绍如何使用名为Teorex Inpaint的1.0.0.2版本的软件来实现这一目标。 首先,我们要理解什么是水印。水印通常是指在图像或视频中添加的半透明标记,它可以是文字...
四、安全性与兼容性 1. 安全检测:在下载和使用此类工具时,需确保来源可靠,避免安装携带恶意软件的版本,保护论坛和个人电脑安全。 2. 兼容性:确认工具是否兼容你的Discuz! X2版本,以及操作系统环境,以保证其...
J2ME全方位开发讲解基础汇总[转帖] 一、J2ME中需要的Java基础知识 现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成...
1.修改自Convert X转帖工具 2.新增批量替换关键词(原来是单个词语替换,可以利用这个...5.新增按颜色屏蔽干扰码 6.新增减少缩进以及优化了首行缩进 7.优化一些小细节 8.重新布局优化显示及方便操作 9.不断更新中...
标题和描述中的“世界编程大赛第一名写的程序”这一知识点,实际上指向了计算机科学与编程竞赛领域的一个重要概念:即在高水平的编程比赛中,优胜者所编写的代码往往蕴含着高级算法、数据结构以及编程技巧。...
"转帖工具插件 for PHPwind 7.5 正式版" 是专门为 PHPwind 7.5 版本设计的一个功能插件,旨在提供便捷的帖子转移功能,帮助管理员或者用户将内容从一个地方轻松移动到另一个地方,而无需直接编辑论坛的原始文件。...
转帖图片提取工具可以对论坛图片附件信息进行清除,只保留图片代码,操作很简单,推荐有需要转帖图片工具的朋友下载 转帖图片提取工具使用方法: 将IP138上处理过的东西复制到上方的编辑框内,点击只要图片,下面...
《一键转帖功能插件 for 帝国CMS 6.0 GBK utf8 V1.0》 本文将深入探讨“一键转帖功能插件”在帝国CMS 6.0系统中的应用与实现,该插件适用于GBK及UTF-8编码环境,旨在提升网站内容的分享与传播效率。我们将从安装...
HTML2UBBMaxcj 是一款专为Softii论坛设计的转帖工具,它主要用于将HTML格式的帖子内容转换成UBB代码,以便在论坛中更好地显示和分享。UBB(Universal BBCode)是一种轻量级的标记语言,常用于网络论坛,与HTML类似,...
然而,在享受论坛便利的同时,用户经常会遇到一系列的问题,尤其是困扰他们的“干扰码”。这些干扰码主要用来防止恶意爬虫的爬取或出于对版权内容的保护,但无疑给正常用户的信息获取带来了不便。为了解决这一问题,...
"一键转帖功能插件 for 帝国CMS v1.0.rar" 是一个专为帝国CMS设计的扩展工具,其主要目标是简化用户在网站上分享内容的过程,提高用户体验。这个插件允许用户轻松地将网站上的文章或信息复制并转发到其他平台,如...
JProfiler是一款功能强大的Java性能分析工具,它可以对Java应用程序、Applets、Java Web Start应用以及应用服务器进行性能监控与分析。通过深入地分析内存使用、线程活动、垃圾回收等关键性能指标,帮助开发人员及...
看到论坛里帖子由精美的图片想转过来,或者批量提取地址时很好用
转帖:本项目是一个聊天机器人的小例子,使用的图灵(www.tuling123.com)提供的聊天api,javaapk之前也发布过一个聊天机器人http://www.javaapk.com/source/1488.html,现在的问答机器人只能分析关键字做一个简单的...
UBB转帖王是一种插件,它能够帮助用户快速去除复制下来的网页内容中的无用空格、文字干扰码、水印和空行等,优化复制内容,便于分享和阅读。 【其他浏览器解决方案】 除了火狐,其他浏览器如搜狗、遨游和世界之窗也...