doc: 文档阅读
This commit is contained in:
@@ -60,6 +60,18 @@
|
||||
- [jstat](#jstat)
|
||||
- [jinfo](#jinfo)
|
||||
- [jstack](#jstack)
|
||||
- [类文件结构](#类文件结构)
|
||||
- [魔数](#魔数)
|
||||
- [class文件版本号](#class文件版本号)
|
||||
- [常量池](#常量池)
|
||||
- [类索引、父类索引、接口索引集合](#类索引父类索引接口索引集合)
|
||||
- [字段集合](#字段集合)
|
||||
- [方法集合](#方法集合)
|
||||
- [属性表集合](#属性表集合)
|
||||
- [虚拟机加载机制](#虚拟机加载机制)
|
||||
- [类加载时机](#类加载时机)
|
||||
- [加载](#加载)
|
||||
- [验证](#验证)
|
||||
|
||||
|
||||
# 深入理解java虚拟机
|
||||
@@ -542,3 +554,84 @@ jinfo -sysprops 5338
|
||||
|
||||
### jstack
|
||||
jstack命令用于生成虚拟机当前时刻的线程快照,即当前虚拟机每一个线程正在执行的方法堆栈集合。该命令主要用于定位线程长时间出现停顿的原因,例如线程间死锁、死循环、长时间等待等。
|
||||
|
||||
|
||||
## 类文件结构
|
||||
class是以字节为基础单位的二进制流,各个数据项排列紧凑,中间没有分隔符。当数据项实际占用的空间超过一个字节时,多个字节之间按照`大端序`来进行排序,即高位字节在前。
|
||||
|
||||
class文件采用一种伪结构来存储数据,该伪结构类似C语言中的结构体,伪结构中只有两种数据类型:
|
||||
- 无符号数: 无符号数属于基本数据类型,u1/u2/u4/u8分别代表长度为1/2/4/8个字节的无符号数,无符号数可以用于描述数字、索引引用、数量值、utf-8编码的字符串值
|
||||
- 表:表是由多个无符号数或其他表组成的复合数据类型,所有表都习惯性以`_info`结尾。
|
||||
|
||||
class文件本质上就是一张表,其组成结构如下所示:
|
||||
| 类型 | 名称 | 数量 |
|
||||
| :-: | :-: | :-: |
|
||||
| u4 | magic | 1 |
|
||||
| u2 | minor_version | 1 |
|
||||
| u2 | major_version | 1 |
|
||||
| u2 | constant_pool_count | 1 |
|
||||
| cp_info | constant_pool | constant_pool_count -1 |
|
||||
| u2 | access_flags | 1 |
|
||||
| u2 | this_class | 1 |
|
||||
| u2 | super_class | 1 |
|
||||
| u2 | interfaces_count | 1 |
|
||||
| u2 | interfaces | interfaces_count |
|
||||
| u2 | fields_count | 1 |
|
||||
| field_info | fields | fields_count |
|
||||
| u2 | methods_count | 1 |
|
||||
| method_info | methods | methods_count |
|
||||
| u2 | attributes_count | 1 |
|
||||
| attribute_info | attributes | attributes_count |
|
||||
|
||||
### 魔数
|
||||
每个class文件的头4个字节被称为魔数,其作用是确定该文件是否是一个能被虚拟机接受的class文件。class文件的魔数为`0XCAFEBABE`。
|
||||
|
||||
### class文件版本号
|
||||
魔数之后的4个字节记录的是class文件的版本号:
|
||||
- 第5、6个字节记录的是minor version(次版本号)
|
||||
- 第7、8个字节记录的是major version(主版本号)
|
||||
|
||||
jdk的主版本号从45开始,jdk 1.0/1.1使用了45的版本号,而每个jdk大版本发布主版本号都会+1。并且,jdk都能兼容以前版本的class文件。
|
||||
|
||||
### 常量池
|
||||
在class主版本/次版本号之后,是常量池入口。
|
||||
|
||||
常量池中主要存放字面量和符号引用。
|
||||
|
||||
### 类索引、父类索引、接口索引集合
|
||||
类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,接口索引集合(interfaces)则是一组u2类型的数据集合。
|
||||
|
||||
class文件通过上述3个字段来确定类的继承关系。
|
||||
|
||||
### 字段集合
|
||||
字段表用于描述接口或类中声明的变量。字段(field)包括类级变量和实例级变量。
|
||||
|
||||
### 方法集合
|
||||
方法集合中同样包含了静态方法和非静态方法。
|
||||
|
||||
### 属性表集合
|
||||
属性表集合用于记录类的一些属性信息,如`final/SourceFile`等。
|
||||
|
||||
## 虚拟机加载机制
|
||||
### 类加载时机
|
||||
类从被加载到内存中开始,到类被卸载,其整个生命周期包含如下环节:
|
||||
- 加载(Loading)
|
||||
- 验证(Verification)
|
||||
- 准备(Preparation)
|
||||
- 解析(Resolution)
|
||||
- 初始化(Initialization)
|
||||
- 使用(Using)
|
||||
- 卸载(Unloading)
|
||||
|
||||
其中,`验证、准备、解析`三个阶段统称为`链接`
|
||||
|
||||
### 加载
|
||||
加载是类加载过程中的一个阶段,在加载阶段虚拟机主要执行如下步骤:
|
||||
- 通过类的全限定类名来获取此类的二进制字节流
|
||||
- 将该字节流所代表的静态存储结构转化为方法区的运行时数据结构
|
||||
- 在内存中生成一个代表该类的`java.lang.Class`对象,作为方法区中这个类数据的访问入口
|
||||
|
||||
### 验证
|
||||
验证是连接阶段的第一步,这一阶段目的是为了确保class文件中字节流包含信息符合当前虚拟机的要求。
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user