文章目录
- 前言
- 一、JVM基础
- 1、cross platform 跨平台
- 2、cross language 跨语言
- 3、什么是JVM呢?一张图告诉你
- 4、java从编码到执行*****
- 5. 从跨平台的语言到跨语言的平台
- 6. jvm与class文件格式
- 7. JVM
- 8. javac的过程
- 9. 常见的JVM实现
- 10. JDK JRE JVM
- 二、Class File Format (class 文件格式)
- 1、测试小程序
- a、T0100_ByteCode01.java
- b、idea打开T0100_ByteCode01.class
- 2、class文件
- 3、Class文件解读
- a、javap 翻译class 文件 (java自带)
- b、jclasslib 翻译class文件(idea插件)
- i、一般信息
- ii、常量池:
- iii、接口、字段
- iv、方法
- v、附加属性 attributes
前言
- 文中所用到的class文件结构思维导图下载:class文件思维导图
一、JVM基础
1、cross platform 跨平台
即任何语言只要编译成 class 文件,在装有JVM任何的系统上 都可以运行。
2、cross language 跨语言
即:有好多语言是在JVM上运行的,这就是夸语言的。
3、什么是JVM呢?一张图告诉你
4、java从编码到执行*****
- 通过 javac 命令:将 java文件 编译成 class 文件
- 通过 java 命令:classloader 加载 class 文件以及 java 类库 到
内存
中进行装载,装载完成后, 然后调用字节码解释器
或者JIT即时编译器
来进行解释 或者 编译。 - 之后 由 执行引擎 进行 执行,最终到OS操作系统。
- 那java是解释执行的还是编译执行的呢?其实
解释和编译是可以混合的
,如果代码用到的次数比较多,会把代码做成 即时编译 即做成本地的编译,就类似c语言在win中编译成exe文件,这样效率会比较高。
5. 从跨平台的语言到跨语言的平台
JVM:是跨语言的平台。
java:是跨平台的语言。
在JVM上能够跑的语言 到目前有100多种,比如下图中的Scala、groovy语言等。
6. jvm与class文件格式
== jvm跟java无关==
7. JVM
- jvm是一种规范 – java virtual machine specifications
https://docs.oracle.com/en/java/javase/13/
https://docs.oracle.com/javase/specs/index.html
- JVM 是 虚构出来的一台计算机
- 字节码指令集(汇编语言)
- 内存管理:栈 堆 方法区等
白话解释:
JVM是一台虚拟出来的一台机器,也就有自己的CPU、内存管理,比如栈、堆、方法区,所以也就有后面的JVM调优等等。
8. javac的过程
9. 常见的JVM实现
-
Hotspot
- oracle官方,我们做实验用的 JVM
- java –version
-
Jrockit
- BEA,曾经号称世界上最快的 JVM
- 被Oracle收购,合并于hotspot
-
J9 – IBM
-
Microsoft VM
-
TaobaoVM
- hotspot深度定制版 ▪
-
LiquidVM
- 直接针对硬件 ▪
-
azul zing
- 最新垃圾回收的业界标杆
- www.azul.com
Hotspot:就是上面所说的第一个JVM类型
mixed mode:就是 上面 1.4说的混合模式,解释和编译混合执行。
10. JDK JRE JVM
-
jdk全称:
java development kit
,其意思是java开发工具包
。jdk是sun公司开发的,jdk包括jre(java runtime environment)java运行环境,一堆java工具[java的编译器(java c.exe),java解释执行器(java.exe)]和java基础的类库(有3000多类,常用的类150多个)。 -
JRE(Java Runtimely Environment)
,java运行环境,只能运行.class文件,不能编译,针对用户。JRE,包含一个JVM(java虚拟机),与java核心类库与其所支持的文件。与JDK不同,它不包含开发工具—编译器,调试器和其他工具。 -
JVM(java Virtual Machine )
,Java虚拟机,Java运行环境。Java虚拟机,是一种虚拟出来的计算机,是通过在实际的计算机上模拟仿真各种计算机功能来实现的。
二、Class File Format (class 文件格式)
分析和学习class文件。目前公司面试很少用到,但是需要学习和了解哈,抱着兴趣去学。
不能抱着功利性去学。
class文件:就是编译完成之后的 .class
文件
1、测试小程序
a、T0100_ByteCode01.java
package com.mashibing.jvm.c1_bytecode;
public class T0100_ByteCode01 {
}
然后编译,生成 T0100_ByteCode01.class
文件。
b、idea打开T0100_ByteCode01.class
如果在idea中打开编译后的 T0100_ByteCode01.class
的文件,就是idea会帮我们进行反编译
,反编译的多了一个默认的无参构造函数,这是默认添加的。
注释是反编译出来的注释
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.mashibing.jvm.c1_bytecode;
public class T0100_ByteCode01 {
public T0100_ByteCode01() {
}
}
2、class文件
-
任何的文件都应该是010101二进制,class如果用一个16进制编辑器(
sublime text 3
)打开,就是如下图所示:
-
class文件是 二进制字节流。
-
数据类型:u1 u2 u4 u8 和 _info (表类型)(
只是逻辑上分的,其实没有数据类型,只有0和1
)(u:Unsigned,意为为无符号的,u1指1个字节;u2指2个字节;u3指3个字节;u4指4个字节;u8指8个字节
)- _info 的来源 是Hotspot 源码中的写法
-
查看
16进制格式classFile
的工具-
sublime
(打开如上图) /notepad
-
idea插件:
Bined
(上面的红框可以查看二进制、八进制、十六进制的文件,当然二进制是最根本的文件格式)
-
-
有很多可以
观察byteCode的方法
:javap
(java自带):下面有使用JBE
可以直接修改JclassLib
idea插件之一
未下载前 是idea自带的
:
将鼠标放在class文件中:
不好观察,所以下载插件:JclassLib
后
-
classfile构成
3、Class文件解读
class就是二进制字节流,那怎么解释呢,看由谁来解释,这里是由java虚拟机 JVM 来解释的
。
常量池是class文件里最复杂的部分
下图就是上面2.2 第一个图片,编译后的class文件,对其进行解读。
== 讲解上图:==
一个小格是一个字节。对十六进制来讲,一个十六进制就是4位。两个十六进制就是一个字节 即8位。(如下图可看出,第一个小格是CA,这是16进制,所以这是一个字节,即8位。)
CAFE BABE
这是java编译后class文件
的抬头,比如其他png、GIF的都有自己独有的抬头。这就是 magic number 魔法数。0000 0034
中,0000
为minor version,小版本号,比如版本是52.0,则minor version就是.0
的概念0034
是major version,大版本号,十进制是52,1.8编译完后就是52,1.9就是53。
1110
:constant_pool_count,常量池里存在常量的个数
;两个字节,216=65536,,最多可放65535个常量
最多是 - 1。- 后面接着就是常量的表
constant_pool
:
其长度为constant_pool_count - 1
的表;这里是10,十六进制 就是15,则 就是15-1=14个常量,为什么要减一,因为常量池数组是从1开始的(平时数组是从0开始)因为最前面保留了一个0,将来可能有一些引用指向会表示不指向任意常量的任何一项,就可以用0来代表。 access flags
:
a、javap 翻译class 文件 (java自带)
这样看不是很清楚,可以通过工具来很清晰的查看,就是java自带的javap
:会把class文件中的内容帮我们翻译好。(从2.2中可以看到)
javap T0100_ByteCode01.class
:显示内容较少,如下,(可通过javap查看参数)
javap -v T0100_ByteCode01.class
:下图中可以看到帮我们翻译出来的 minor version、major version、flags 等名称。
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
:后面的 ACC_SUPER 就是:该标志必须为真,JDK1.0.2之后编译出来的内容必须为真,指明invokespectial指令使用新语义
b、jclasslib 翻译class文件(idea插件)
使用 jclasslib 打开 class 文件,下面并进行分析和说明
i、一般信息
这里包含了class 文件结构的大多数基础信息,当然最重要的还是常量池。
- 本类索引,就是 this class :
cp_info #7 <com/mashibing/jvm/c1_bytecode/T0100_ByteCode01>:
后面的<com/mashibing/jvm/c1_bytecode/T0100_ByteCode01>
就是本类的名称,cp_info #7
就是在常量池的7号存的。绿色可以点击,点击过去就是 常量池的7号位置。 - 父类索引,就是 super class:
cp_info #2 <java/lang/Object>
:后面的还是父类名称,前面就是父类存储在常量池的2号位置。 - 接口计数 即 interfaces count。
- 字段计数 即 fields count。
- 方法计数 即 methods count。
- 属性计数 即 attributes count。
ii、常量池:
- 常量类型有很多种,如下图所示1,3,4,5,6到18,但是没有2,标记:常量池的每一种类型前边都有一个一个字节的标记,用的最多的是第一个:CONSTANT_Utf8_info ,代表 utf8的字符串。(
下图的思维导图可从文章开头的前言中找到并下载
)
jclasslib 打开的常量池 1号位置
是Methodref_info
文件:存的是方法引用信息,从思维导图中可以看出存的如下图所示,包括三个 1是标记10,2是index2个字节指向其他常量池 ,3是index2个字节指向其他常量池。
1号位置 methodref_ref
中的 类名cp_info #2
:意思是指向类的名字在2号位置,这里又存在了4号位置。
1号位置 methodref_ref
中的 描述cp_info #3
:指向的是3号位置的name和type。可以看出
<init>
是构造函数
<()v>
()是指 没有参数,V是指返回类型为void类型。
iii、接口、字段
因为2.1测试小程序很简单,没有接口和字段,所以这里为空
iv、方法
测试小程序虽然很简单,啥都没有
但是生成一个默认的 构造函数。
这里也有最重要的code 环节,因为函数里会有code的哈,这里会有大量的指令集(JVM大约定义256个左右)
v、附加属性 attributes
这里默认的就是java的类名称