JVM定义
跨语言的平台
字节码文件的运行环境
- 只要能够依据JVM规划(JVM Specification)编译成字节码文件(.class)的语言都可以在JVM环境上运行。
- JVM本身与java没有绝对关系,而是针对于字节码文件,符合规范的.class文件都能够享受JVM带来的良好的运行环境。
- JVM本身是一种规范
class file format
本质:二进制字节流
查看方式:
- 查看十六进制格式的ClassFile
- subline/notepad
- IDEA插件-BinEd
- 其他ByteCode的观察方式:
- javap + 一个指令 + class文件地址
- JBE(Java ByteCode Editor)-可以直接修改
- JClassLib - IDEA插件之一 内容:
- Magic Number
- "CAFEBABE"
- constant_pool_count:常量池数据量
- constant_pool:常量池中数据
- access_flags:修饰符public、final等信息
- this_class
- super_class
- field_count
- fields
- interfaces_count
- interfaces
- methods_count
- methods
- attributes_count
- attributes
class的可移植性
- 只要能够编译成为.class的语言,都具备移植性,原因在于:只要当前内核环境下存在符合当前内核的JVM进程(比如:Windows有windows版本的JVM,MacOS有MacOS的JVM,Linux有...),有JVM存在,class文件都能够直接运行,JVM解决了与内核或硬件适配的问题。因此只要能够编译成.class的语言都具备“一次编译,到处运行的能力”,其主要依托于有JVM存在。
JVM版本实现
- Hotspot:orcle官方开发,jdk使用的官方JVM;
- Jrockit:BEA开发,被Orcle收购,合并入Hotspot;
- J9:IBM
- Microsoft VM
- Taobao VM:Hotspot深度定制版
- Liquid VM:直接针对硬件
- azul zing:最新垃圾回收的标杆
JDK
Java从编译到执行
对象的创建
-
创建对象:
1. 分配内存空间; 2. 为实例变量赋初值; 3. 设置对象头信息,包括对象的hashcode(只有对hashcode进行了调用才会存入进来),GC分代年龄,元数据信息; 4. 执行构造器进行初始化;
对象在内存中的布局
普通对象
-
对象头:(12字节)
-
markword(8字节):关于锁状态、锁升级、hashcode、gc信息等;
-
class pointer(4字节或8字节):类型指针,获取Clazz对象的途径之一,对象类型的标识;
- 默认32GB内存下,32位寻址能力足够,JVM开启compress class pointer,因此会压缩至4字节;
-
-
实例数据:instance data
- 类中成员变量,具体大小根据变量数量和类型决定;
- 比如:一个int类型,那么就需要占4个字节;如果是long类型,就需要占8字节;
-
对齐:padding
- 保证对象所占字节数能够被8整除,从而读取的时候效率更高(cpu读取数据是根据总线的宽度来读取,保证是8字节的倍数,读取效率高);
- 如果当前所占内存不是8的倍数,会自动通过padding进行空间的补齐;
指针压缩原因:
-
32位对应能够记录2的32次方-1个不同的地址,约等于4G个数量级;
-
每个java对象大小必然是超过8字节(markword已经超过8字节);
-
每个对象只需要对应一个起始地址;
-
综上:32GB内存下,32位寻址能力必然足够,可开启指针压缩,节省空间。
数组对象
相比普通对象,多一个属性length属性(4字节)
JVM内存模型
线程共享
- 堆区
- 绝大部分对象完成生命周期的场所,GC的核心区域;
- 方法区
- 存放类信息、各种常量池、runtime constentpool data;
线程私有
- 虚拟机栈
- 普通方法的调用栈,每个方法对应一个栈帧,当前方法对应当前栈帧;
- 本地方法栈
- native method调用栈,当前方法对应当前栈帧;
- 程序计数器
- 记录所执行到的指令位置,线程重新获取CPU时间时,继续从此位置开始执行;