[介绍]
本文给出一个java字节码的例子。 纸上得来终觉浅,绝知此事要躬行。
本文将详细解释一个字节码例子。 看过一些相关的文章和书籍,但是给出的例子一般都更加简化,然后给出理论解释。
我自己通过认真分析此字节码,基本上把重要部分都cover了。
本文的例子来自于: [KB JVM - How to print readable bytecode from class file -> An example of bytecode - java]
[一些note]
关于字节码的一些note,copy到这里
java字节码与汇编程序(Assembly)有点类似.
区别在于:1)JVM没有寄存器,所有操作均在Stack上执行 2)但是有局部变量表
load : slot# --> stackstore: slot# <-- stackconst: const --> stack
这里还有个简单的例子: [P161 Ref 1 zzm]
note:每个方法所使用的局部变量表、栈的大小在编译时确定
note:局部变量表 0 - this, 1..m m个方法参数,剩下的是可用的slot
note:调用某个方法之前,会将局部变量表准备好,因为一个线程中的所有方法共享同一个局部变量表
[Java Source Code]
public class Volatile { private volatile int field = 0; public void increase(){ field++; } public static void main(String[] args){ Volatile ex = new Volatile(); ex.increase(); } }
[ByteCode]
javap -verbose Volatile.class
下面的以BY:开头的是我的注释
都是用英文写的,因为我当时的编辑工具中文显示乱码。
D:\baoying_no_index\360CloudDisk_Compiling_Output\BaoyingCleanProject\bin>javap -verbose Volatile Compiled from "Volatile.java" public class Volatile extends java.lang.Object SourceFile: "Volatile.java" minor version: 0 major version: 50 Constant pool: const #1 = class #2; // Volatile const #2 = Asciz Volatile; const #3 = class #4; // java/lang/Object const #4 = Asciz java/lang/Object; const #5 = Asciz field; const #6 = Asciz I; const #7 = Asciz <init>; const #8 = Asciz ()V; const #9 = Asciz Code; const #10 = Method #3.#11; // java/lang/Object."<init>":()V const #11 = NameAndType #7:#8;// "<init>":()V const #12 = Field #1.#13; // Volatile.field:I const #13 = NameAndType #5:#6;// field:I const #14 = Asciz LineNumberTable; const #15 = Asciz LocalVariableTable; const #16 = Asciz this; const #17 = Asciz LVolatile;; const #18 = Asciz increase; const #19 = Asciz main; const #20 = Asciz ([Ljava/lang/String;)V; const #21 = Method #1.#11; // Volatile."<init>":()V const #22 = Method #1.#23; // Volatile.increase:()V const #23 = NameAndType #18:#8;// increase:()V const #24 = Asciz args; const #25 = Asciz [Ljava/lang/String;; const #26 = Asciz ex; const #27 = Asciz SourceFile; const #28 = Asciz Volatile.java; BY: https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings { public Volatile(); Code: --BY: Stack=2 max Stack size --BY: Locals=1, it means the Slot capacity is 1. It contains 'this' only. --BY: Args_size=1. only 'this' as default parameter. Stack=2, Locals=1, Args_size=1 0: aload_0 BY: push slot#0 ('this') to Stack. after Stack: this 1: invokespecial #10; //Method java/lang/Object."<init>":()V BY: invoke parent constructor. After Stack: empty 4: aload_0 BY: push slot#0 ('this') to Stack. Why again? A: it is required by the following(#6) putfield.(20150630) After Stack: this 5: iconst_0 BY: push 0 to Stack. After Stack: (top)0, this (bottom) 6: putfield #12; //Field field:I BY: assign field#12 with 0 (const #12 = Field #1.#13; // Volatile.field:I). After Stack: empty. 9: return LineNumberTable: line 9: 0 line 11: 4 line 9: 9 LocalVariableTable: Start Length Slot Name Signature 0 10 0 this LVolatile; // public void increase(){ // field++; // } public void increase(); Code: Stack=3, Locals=1, Args_size=1 0: aload_0 BY: push 'this' to Stack. slot #0 is 'this'. why aload_0 is required?. A: It is used by the last ( line #7 put field) (20150630) . after: Stack:(top) this (bottom) 1: dup BY: dup the top of the stack, why dup is required?. A: it is used by the following(line #2) getfield. Although the getfile/putfied spec does not mention that it is required to put the 'this' side of the field, it is required! another example here http://cs.au.dk/~mis/dOvs/jvmspec/ref--18.html (20150630) after: Stack:(top)this, this (bottom) 2: getfield #12; //Field field:I BY: push the field #12 reference to Stack. after: Stack:(top)field #12, this(bottom) 5: iconst_1 BY: push 1 to Stack. Stack:(top)1, field #12, this, this(bottom) 6: iadd BY: pop 2 values and push adding result back.. after: Stack:(top) value of field #12+1, this(bottom) 7: putfield #12; //Field field:I BY: pop 2 values, set field #12 value. after: Stack:(top) (bottom) 10: return LineNumberTable: line 14: 0 line 15: 10 LocalVariableTable: Start Length Slot Name Signature 0 11 0 this LVolatile; // public static void main(String[] args){ // Volatile ex = new Volatile(); // ex.increase(); // } //const #21 = Method #1.#11; // Volatile."<init>":()V //const #22 = Method #1.#23; // Volatile.increase:()V public static void main(java.lang.String[]); Code: Stack=2, Locals=2, Args_size=1 0: new #1; //class Volatile BY: create a new Volatile object, after: Stack (top)ex(bottom) 3: dup BY:after: Stack (top)ex,ex(bottom) 4: invokespecial #21; //Method "<init>":()V BY:initialize ex, top popped for this instructino after: Stack (top)ex(bottom) 7: astore_1 BY: save ex to Slot #1 .after: Stack (top)ex(bottom) 8: aload_1 BY: save ex back to stack .after: Stack (top)ex(bottom). Note, no change for stack, after astore_1 and aload_1, but the Slot #1 saved value 'ex' why it is required? Because the following invokation will take Slot. The Slot should prepare Slot[0] = this, Slot[1..m] as arguments. (20150630) 9: invokevirtual #22; //Method increase:()V 12: return LineNumberTable: line 19: 0 line 20: 8 line 21: 12 LocalVariableTable: Start Length Slot Name Signature 0 13 0 args [Ljava/lang/String; 8 5 1 ex LVolatile; }
相关推荐
基于Java字节码的混淆技术研究 基于Java字节码的混淆技术研究
NULL 博文链接:https://andilyliao.iteye.com/blog/899925
将C语言转换为Java字节码或可以直接解释执行的编译器 作为一个学习项目 可以解释为执行大多数C或编译为Java字节码 玩具级,未添加许多功能,也没有优化 支持的 支持所有基本陈述 解释器:支持指针,数组,结构和...
今天用了jmock对进行单元测试编码,发现一个比较奇怪的语法,static使用方法,见下面例子
主要包含 java.text包中工具类的详细使用;包含源码和字节码。
Java字节码的符号量化信息流分析 项目页面 抽象的 现实世界中的计算机系统从来都不是 100% 安全的,因此我们需要衡量它们的安全性。 举一个简单的例子,假设一个攻击者试图猜测一个密码:如果他的猜测是正确的,...
机智 Tact 是一个 Java 程序和包,用于将运行时检查插入到 Java 字节码中。 这些检查的目标是通过确保只有预期线程访问任何对象(通过单独所有权或持有适当的锁)来帮助多线程程序的开发。例子运行 tact 最方便的...
3. 平台无关性:Java 程序在编译后生成的是字节码(bytecode),而不是特定操作系统的机器码。这使得 Java 程序可以在不同的操作系统上运行,实现了“一次编写,到处运行”的理念。 4. 自动内存管理:Java 使用垃圾...
JavaAgent技术的Demo,agentmain方式 采用Javaassist技术实现字节码修改,VirtualMachine技术实现运行时代码织入
jvm-tail-递归在Java字节码上执行尾部递归优化的Java库。它只是将函数中的最终递归方法调用替换为goto到同一函数的开头。该项目使用执行字节码操作。例子倒数至零一个简单的尾递归函数,倒数为零:前后static void ...
JavaAgent技术的Demo,agentmain方式 采用Javaassist技术实现字节码修改,VirtualMachine技术实现运行时代码织入
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...
在运行状态中,对于任意一个类能够获取类中的所有属性和方法,对于任意一个对象能够调用对象中的属性和方法,这种动态获取属性和方法的机制:反射。 设计模式1(单例,工厂) 设计模式2(观察者,适配器) 设计模式...
这个工具的目的是让带有相互依赖的注解的声明变得有意义,这种依赖的一个例子是 Spring Boot 中的 @Autowire:在 Spring Boot 中,一个用 @Autowire 标记的函数将获得返回的值由带有@Bean注解的函数调用,前提是该...
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...
Java磨床将Java字节码编译为微控制器程序集。 当前支持MSP430,dsPIC,6502 / 6510、68000,MIPS,TMS9900和Z80,平台包括Commodore 64,Sega Genesis,Atari 2600,Apple IIgs,ChipKit(PIC32),TI99,TI84,...
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...
Kotlin DSL封装了ObjectWeb的ASM字节码操作库。 (尤其是asm-tree 。) 局限性 由于DSL位于Kotlin中,因此有一些保留字会妨碍我们的工作。 为了解决此问题,我们为属性提供了文字名称,并使用反引号转义,以及在保留...