本篇博客是对Java bytecode:这篇文章的翻译和解读,原文链接在这
http://www.ibm.com/developerworks/library/it-haggar_bytecode/index.html
如有不正之处还请各位指教,不喜勿喷,相互交流才能进步。
转载请注明出处,谢谢。
下面正片开始
javac Employee.java
javap -c Employee > Employee.bc
Generating bytecode
先将
java
源码进行编译后再用
javap
命令进行反编译并添加
-c
参数来获得类的字节码。获得字节码如下:
根据原文解读可大致猜测,
Employee.java
源码应该是这样的:
由此可以发现:前五行的字节码是用哪个类生成的,这个类的定义,这个类是从哪个类继承的,这个类的构造方法和其他的方法。下一步字节码将这个类的构造方法罗列出来,之后又将这个类的所有方法和与之相关的字节码用字典序罗列出来(这里我尝试了一下发现字节码中方法并没有按照字典序排序..不知是否是我的理解错误,测试图如下)。
抛开上面无关紧要的部分,继续。。。
这时候你可能会发现,特定的操作码的前缀a和i
这个操作码的前缀’a’表示的意思为:说明正在操作的是一个对象的引用。
同理’i’表示的意思为:说明正在操作的是一个整型变量
除了’a’和’i’还有以下几种操作码前缀:
‘b’:说明正在操作的是byte类型的变量
‘c’:说明正在操作的是char类型的变量
‘d’:说明正在操作的是double类型的变量
等等。。。
这里要注意:独立的代码一般会被jvm解析为操作码,多重的操作码指令一般会被解析为字节码。
The details
这里为了更深入的理解jvm是如何执行字节码的,我们要理解一下jvm。
Jvm是基于堆栈的,对于jvm来说每一个线程都会有一块独立的堆栈,堆栈中存储着栈帧,当线程中有方法被调用的时候就会创建一块栈帧并将其压入栈中,栈帧又由如下几块组成:操作数栈,局部变量区和一块当前线程所拥有的的类的引用(类的引用保存在常量池中)。
对于局部变量区来说,它既存储方法的参数,也存储方法中产生的一些中间变量。对于普通方法(静态方法)而言局部变量区首先存储的是方法的参数(从0开始),接着再存储方法中产生的局部变量。但是对于构造方法或者是实例方法而言,首先存储的是对象的引用(从0开始),接着第一个参数存1号位置,第二个参数存第二个位置,以此类推。对于静态方法来说,由于静态方法没有是类所拥有的,与对象无关,因此它的第一个参数存0号位置,第二个参数存1号位置,以此类推。。。
局部变量区的大小在编译的时候已经决定了,它主要取决于参数和中间变量的个数和大小
操作数栈用栈来push和pop值,一些特定的指令集会将操作数压入栈中,其他的指令会将这些操作数取走,并将执行的结果再次压入栈中。
上面一段是java源码,下面一段是相应的字节码。
这一段字节码由3个指令集组成。
先看第一个指令集 aload_0 首先根据之前讲的,’a’开头说明操作的是一个引用,结尾的0表示的是从局部变量区中取出放在0号位置的那个变量放入操作数栈,那么为什么要用aload而不用iload呢?我们看一下这个方法是一个实例方法,实例方法的局部变量区的0号位置存储的是对象引用(this),因此要用’a’开头。所有的一切是那么解释通了。还有一个问题,jvm为什么要取this引用呢?因为我们要用this引用来传递实例数据,名字等信息。
再看第二个指令集getfield #5,这个指令用来获取变量从一个对象中,当这个指令执行的时候,处于操作数栈顶端的this引用被拿出,和后面的#5组成一个索引去常量池中寻找相应属性(这里是找name,因为要获取name属性的引用)的引用,当这个引用找到并抓取了之后,将结果放入操作数栈中。
最后一个指令集areturn ,从这个方法中返回对应返回值的引用,并将这个返回值的引用从操作数栈中取出,压入调用方法的操作数栈中(栈帧中)。
下面讲一下最左边的数字是怎么来的,先上两张图:
相信你一定能够看懂(我不会说是因为我懒而不想翻译那么大一段英文。。。这里其实体现了java的平台无关性)
接着我们看一下构造函数的字节码:
首先第一行字节码跟我们上面分析一样,将构造方法的this引用取出来压入操作数栈中。
第二行字节码是调用父类的构造方法,因为所有的没有显示继承的类都隐式的继承的Object类,因此这里是调用了Object类的构造方法。也就是说,该构造方法的java源码其实应该是这样的:
跟之前分析的一样,当这行字节码执行完后,this引用从操作数栈中移除。
接下去的两行字节码aload_0和aload_1,就是将this引用和构造方法的第一个参数取出(不明白为什么的小伙伴请再阅读一遍局部变量区的那里哈),放入操作数栈中。
接下去的putfield #5这行字节码就是将上一步压入操作数栈中的this引用和strName值取出,并通过this和#5找到相应的strName引用将这个strName值赋给它。
下面那个给idNumber赋值的同理。
最后来看看最后5步aload_0
,
aload_1
,
iload_2
,
invokespecial #6 <Method
void storeData(java.lang.String, int)>
,
return
。
前三条指令分别将this引用,strName值,idNumber值分别取出并压入操作数栈,注意this引用必须要被压入,因为这个实例方法正在被调用。如果这个方法是静态方法的话,this引用就不必被压入栈中,但是strName和idNumber必须要被压入到操作数栈中,因为他们是storedData方法的参数。因此当storedData方法执行的时候,this引用,strName和idNumebr分别占据storedData方法的局部变量区的0,1,2个索引。
Size and speed issues
这个模块就是比较两种相同功能的代码用怎么写比较快,解析成的字节码比较数量比较少。
下面看一下这两种线程同步方式解析所产生的的字节码数量的区别:
原文说道第一种方式大概要比第二种方式要快13%左右。但是我认为这仅限于方法内部都需要同步的情况,当方法只需要部分同步的时候,这时候在高并发情况下,直接加锁的方式效率显然要低于synchrnized块的方式。
相关推荐
标题中的“深入字节码 -- 玩转 ASM-Bytecode1”暗示了本文将探讨如何使用ASM库来操作和理解Java字节码。ASM是一个Java字节码操控和分析框架,它允许用户动态生成和修改Java类和注解。在描述中提到,前一篇博文中介绍...
Java Bytecode Editor是修改和分析java字节码结构和类文件的有效工具:下载解压后,双击jbe. bat(Windows)或jbe.sh(Linux)即可运行JBE。src目录下的是JBE的源码。
一种修改和分析java字节码结构和类文件的有效工具, 它是JBE-Java Bytecode Editor 0.1 升级版. 履历简介: 1.原始Jclasslib bytecode viewer 3.0字节码查看功能 2.继续维护升级为:JBE-Java Bytecode Editor 0.1字节...
"Bytecode-Viewer-2.9.22.jar"和"jclasslib-library.jar"是两个非常重要的工具,它们为开发者提供了查看和操作Java字节码的能力。 1. **Bytecode Viewer**: - **概念**:Bytecode Viewer是一个开源的Java字节码...
Java-Bytecode-Editor(简称JBE)是一款专为Java开发者设计的类文件编辑工具,它允许用户直接对编译后的.class文件进行编辑和修改。这个工具对于理解、调试和优化Java字节码非常有帮助,尤其是在处理底层代码或者...
`Scala-FX-Bytecode-Viewer` 的核心特性是并排显示源代码和字节码的能力。这种并排视图让开发者可以轻松地比较源代码与字节码之间的差异,这对于教学、分析性能问题或调试混淆的代码尤其有用。通过这种方式,开发者...
java抓取技术源码 小傅哥的《字节码编程》- 文章涉及源码 前言 初识字节码编程是从使用非入侵的全链路监控开始,在这之前我所了解的如果需要监控系统的运行状况,通常需要硬编码...Javaagent和字节码操作,在字节码操
文档中提到的内容部分通过一个简单的Java类和其对应的字节码来演示了如何解读和理解字节码。 总而言之,Java字节码是Java平台的核心技术之一,它使Java程序具有跨平台的特性,并且为基于JVM的多种编程语言提供了一...
Java字节码编辑器是一种工具,它允许开发者直接编辑Java程序编译后的`.class`文件,而不是反编译后再重新编译。这种编辑器对于理解、调试和优化Java代码非常有用,尤其是对于那些无法访问源代码或者需要进行底层操作...
Java字节码是Java编程语言的核心组成部分,它是Java程序在虚拟机(JVM)上运行的基础。当你编写一个Java源代码文件(.java),通过编译器...如果你对JVM和字节码有浓厚的兴趣,那么这个资源将会是你宝贵的参考资料。
这种方法确保了一致性,减少了错误,并简化了翻译过程,类似于字节码作为中间表示来优化和促进高级编程语言在不同平台上的执行。 通俗解释: Bytecode 模式使行为由数据而不是代码驱动。 gameprogramm
Java字节码是Java虚拟机的指令集 graph TD A[Java Code] -->|Compiled| B(Bytecode) B --> C{Run} C -->|bytecode| D[Windows JVM] D --> K[Windows Instructions] C -->|bytecode| E[Unix JVM] E --...
- **bytecode verifier**: 字节码验证器,是Java虚拟机的一个组成部分,负责确保字节码的安全性和完整性。 - **Central Processing Unit (CPU)**: 中央处理器,是计算机的核心部件,负责解释并执行指令。 - **...
- **解析**: 运行Java字节码文件(.class文件)时,应使用`java`命令,并指定类名(不含`.class`后缀)。 - **扩展**: `javac`命令用于编译Java源代码文件(.java文件)。 ##### 题目10: Suppose you define a Java...
在Java中,字节码(Bytecode)是程序经过编译后的中间表示,可以直接由Java虚拟机(JVM)执行。由于字节码是明文的,如果直接暴露,可能会导致知识产权泄露,因此对其进行加密至关重要。 字节码加密通常包括以下几...
#### Bytecode (字节码) - **定义**: 由 Java 编译器生成的中间代码。 - **特点**: 与平台无关,由 Java 虚拟机 (JVM) 执行。 - **优点**: 允许 Java 程序在不同的平台上运行而无需重新编译。 #### Callback ...
Java字节码是Java虚拟机的指令集 graph TD A[Java Code] -->|Compiled| B(Bytecode) B --> C{Run} C -->|bytecode| D[Windows JVM] D --> K[Windows Instructions] C -->|bytecode| E[Unix JVM] E --...
- **Overview**: Provides insights into the internal structure of Java class files and the bytecode format, essential for understanding how the JVM executes Java code. - **Key Areas**: - **Class File ...
Java Bytecode Editor(简称JBE)是一款强大的工具,专门用于查看和分析Java字节码。在深入探讨JBE的功能和用途之前,我们首先需要理解什么是Java字节码。Java字节码是Java源代码经过Java编译器编译后的中间表示形式...