JVM入门
JDK、JRE和JVM的包含关系
JVM特点
- 有的说法说classLoader不属于JVM,概念无所谓
- 解释和编译混合
- 跨语言的平台
- JVM和java无关
任何语言-编译或动态生成->.class文件-运行在->JVM
- JVM是一种规范
java virtual machine specifications - 虚构出来的一台计算机
- 字节码指令集(汇编语言)
- 内存管理:栈 堆 方法区等
javac的过程
常见的JVM实现
java -version就可以看到自己用的JVM的详情
- HotSpot:
oracle官方的实现(最早是sun,后来被Oracle收购) - Jrockit:
BEA,曾号称世界最快JVM,被Oracle收购合并于HotSpot - J9:
IBM的实现 - Microsoft VM
- TaobaoVM:
HotSpot深度定制版 - LiquidVM:
直接针对硬件 - azul zing:
最新垃圾回收的业界标杆,据说特别贵,垃圾回收特别快
class文件格式(Class File Format)
面试基本不会问,当成兴趣来学
- class文件是一个二进制的字节流;
- 数据类型:u1 u2 u4 u8和_info(表类型)
_info 的来源是Hotspot源码里的写法
class文件的格式设计的特别牛批,很紧密,没有任何分隔符,得到了很多大牛的认可,所以他们设计语言时会选择翻译成class运行在JVM上
需配合官网JVM规范第七节(java的汇编语言).
认识编译生成的class文件
创建一个空类
package character01;
/**
* @Author laimouren
* @Date 2022/1/7 9:55
*/
public class Empty {
}
编译之后查看它的class文件,IDEA自动反编译,可以看到多了一个无参构造方法
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package character01;
public class Empty {
public Empty() {
}
}
IntelliJ IDEA可以安装一个BinEd的插件打开即可查看class文件
如果用SublimeText打开的话,它是以16进制打开的:
cafe babe 0000 0034 0010 0a00 0300 0d07
000e 0700 0f01 0006 3c69 6e69 743e 0100
0328 2956 0100 0443 6f64 6501 000f 4c69
6e65 4e75 6d62 6572 5461 626c 6501 0012
4c6f 6361 6c56 6172 6961 626c 6554 6162
6c65 0100 0474 6869 7301 0021 4c63 6f6d
2f65 7861 6d70 6c65 2f64 656d 6f2f 6a76
6d2f 456d 7074 7943 6c61 7373 3b01 000a
536f 7572 6365 4669 6c65 0100 0f45 6d70
7479 436c 6173 732e 6a61 7661 0c00 0400
0501 001f 636f 6d2f 6578 616d 706c 652f
6465 6d6f 2f6a 766d 2f45 6d70 7479 436c
6173 7301 0010 6a61 7661 2f6c 616e 672f
4f62 6a65 6374 0021 0002 0003 0000 0000
0001 0001 0004 0005 0001 0006 0000 002f
0001 0001 0000 0005 2ab7 0001 b100 0000
0200 0700 0000 0600 0100 0000 0700 0800
0000 0c00 0100 0000 0500 0900 0a00 0000
0100 0b00 0000 0200 0c
class文件格式解读
从前到后的依次是: Magic Number, Minor version, Major version,等等,具体见下面class file规范
每个16进制的数字占4位,1个字节是8位,所以下面一个方格代表一个字节.
java的class文件的Magic Number一般都是 cafe babe
class文件版本号version,JDK7默认是51.0,JDK8默认是52.0,依次递增;51 52都是Major Version, 后面的小数位是Minor Version
有时候我们用JDK8编译的项目在JDK7的环境上跑时,会抛异常:xxxx version 52.0
后面是constant_pool_count
再后面是(constant_pool_count-1) 个 constant_pool,从 #1 开始,因为 #0 做了个预留,代表没有任何引用指向它.
显示class信息的工具
- javap
javap -v EmptyClass.class 输出:
Classfile /Users/liweizhi/IdeaProjects/msb-class/demo/target/classes/com/example/demo/jvm/EmptyClass.class
Last modified 2020-3-23; size 297 bytes
MD5 checksum a2e3e21cc6e7c6b5d8035663b369a23c
Compiled from "EmptyClass.java"
public class com.example.demo.jvm.EmptyClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#13 // java/lang/Object."<init>":()V
#2 = Class #14 // com/example/demo/jvm/EmptyClass
#3 = Class #15 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 Lcom/example/demo/jvm/EmptyClass;
#11 = Utf8 SourceFile
#12 = Utf8 EmptyClass.java
#13 = NameAndType #4:#5 // "<init>":()V
#14 = Utf8 com/example/demo/jvm/EmptyClass
#15 = Utf8 java/lang/Object
{
public com.example.demo.jvm.EmptyClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 7: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/demo/jvm/EmptyClass;
}
SourceFile: "EmptyClass.java"
- JBE,可以查看并修改
- jclassLib bytecode viewer,IDEA的插件,便捷好用
安装插件
光标放在class类体里
点击view -> Show Bytecode With jclassLib
在Java语言规范中,指明了:long和double的读写操作应该是原子的。