初识JVM byte code
来源:互联网 发布:星星知多少的自频道 编辑:程序博客网 时间:2024/05/16 08:56
关于JVM和其上的byte code,网上其实有足够多的资料了,我这里就简单做个提纲和介绍,权当记录吧。
stack-based VM
Java byte code运行在JVM上,就像机器指令运行在物理机上,是需要遵循这个机器的指令规范的。所以认识JVM byte code,是需要稍微了解下JVM的。JVM是一个基于栈(stack-based)的虚拟机。很久以前我还写过类似 简单的虚拟机 。
基于栈的虚拟机其操作数和指令运算的中间结果全部都在一个虚拟栈中,与之对应的是基于寄存器(register-based)的虚拟机,其操作数和指令运算结果会存放在若干个寄存器(也就是存储单元)里。x86机器就可以理解为基于寄存器的机器。
byte code其实和x86汇编代码本质一样,无非是对应机器制定的一堆指令,这里可以举例说明下两类虚拟机的不同:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 1
- 2
- 3
关于两类实现的比较,网上也有不少资料,例如 Dalvik 虚拟机和 Sun JVM 在架构和执行方面有什么本质区别? 。
至于有人说基于栈的虚拟机更利于移植,我不是很理解,因为即使是基于寄存器的实现,也不一定真的必须把这些寄存器映射到物理机CPU上的寄存器,使用内存来模拟性能上跟基于栈的方式不是八九不离十吗?
了解了JVM的这个特点,JVM上的各种指令就可以更好地理解,如果要理解JVM如何运行byte code的,那还需要了解JVM内部的各种结构,例如符号解析、class loader、内存分配甚至垃圾回收等。这个以后再谈。
byte-code
*.class 文件就已经是编译好的byte code文件,就像C/C++编译出来的目标文件一样,已经是各种二进制指令了。这个时候可以通过JDK中带的 javap 工具来反汇编,以查看对应的byte code。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
编译该文件: javac Test.Java 得到 Test.class ,然后 javap -c Test 即得到:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
这个时候对照着JVM指令表看上面的代码,比起x86汇编浅显易懂多了,秒懂,参考 Java bytecode instruction listings 。JVM中每个指令只占一个字节,操作数是变长的,所以其一条完整的指令(操作码+操作数)也是变长的。上面每条指令前都有一个偏移,实际是按字节来偏移的。 想起Lua VM的指令竟然是以bit来干的
从上面的byte code中,以x86汇编的角度来看会发现一些不同的东西:
局部变量竟是以索引来区分: istore_1 写第一个局部变量, istore_2 写第二个局部变量,第4个局部变量则需要用操作数来指定了: istore 4
函数调用 invokespecial #1 竟然也是类似的索引,这里调用的是 Object 基类构造函数
常量字符串也是类似的索引: ldc #2
*.class 中是不是也分了常量数据段和代码段呢
以上需要我们进一步了解 *.class 文件的格式。
class file format
class 文件格式网上也有讲得很详细的了,例如这篇 Java Class文件详解 。整个class文件完全可以用以下结构来描述:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
这明显已经不是以区段来分的格式了,上面提到的函数索引、常量字符串索引,都是保存在 constant_pool 常量池中。常量池中存储了很多信息,包括:
各种字面常量,例如字符串
类、数据成员、接口引用
常量池的索引从1开始。对于上面例子 Test.java ,可以使用 javap -v Test 来查看其中的常量池,例如:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
每一个类都会有一个常量池。
summary
原文 http://codemacro.com/2015/03/31/intro-java-bytecode/
- 初识JVM byte code
- 初识JVM byte code
- 初识JVM byte code
- Byte Code
- 初识JVM
- JVM初识
- 初识jvm
- 初识JVM
- 初识JVM
- 初识JVM
- 初识JVM
- 初识JVM
- JVM学习(初识JVM)
- 【JVM】初识JVM
- Java Code To Byte Code
- Java Code To Byte Code
- 初识JVM-JVM运行机制(1)
- 初识JVM-JVM运行机制(2)
- 手机端 不断向上或者向下跳动的 提示箭头
- Python 存储模型
- Codeforces Round #407 (Div. 2)
- Codeforces 510D Fox And Jumping【数论+Dp+压缩空间】好题~
- 处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
- 初识JVM byte code
- ios学习网址
- SAMBA文件服务器案例
- sklearn.model_selection.GridSearchCV 中文
- 完美兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面js代码
- java中的ArrayList 、List、LinkedList、Collection关系详解
- JESD79-4 第4章 SDRAM命令描述与操作(4.28-4.29)
- swift中snapkit
- String 源码浅析