Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
清新范er
JavaGuide
提交
6abc003b
J
JavaGuide
项目概览
清新范er
/
JavaGuide
与 Fork 源项目一致
从无法访问的项目Fork
通知
4
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JavaGuide
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6abc003b
编写于
4月 01, 2021
作者:
G
guide
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update 类文件结构.md
上级
4de06051
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
44 addition
and
32 deletion
+44
-32
docs/java/jvm/类文件结构.md
docs/java/jvm/类文件结构.md
+44
-32
未找到文件。
docs/java/jvm/类文件结构.md
浏览文件 @
6abc003b
点击关注
[
公众号
](
#公众号
)
及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。
<!-- TOC -->
<!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6 orderedList=false} -->
<!-- code_chunk_output -->
-
[
类文件结构
](
#类文件结构
)
-
[
一 概述
](
#一-概述
)
-
[
二 Class 文件结构总结
](
#二-class-文件结构总结
)
-
[
2.1 魔数
](
#21-魔数
)
-
[
2.2 Class 文件版本
](
#22-class-文件版本
)
-
[
2.3 常量池
](
#23-常量池
)
-
[
2.4 访问标志
](
#24-访问标志
)
-
[
2.5 当前类索引,父类索引与接口索引集合
](
#25-当前类索引父类索引与接口
索引集合
)
-
[
2.6 字段表集合
](
#26-字段表集合
)
-
[
2.7 方法表集合
](
#27-方法表集合
)
-
[
2.8 属性表集合
](
#28-属性表集合
)
-
[
2.1 魔数(Magic Number)
](
#21-魔数magic-number
)
-
[
2.2 Class 文件版本号(Minor&Major Version)
](
#22-class-文件版本号minormajor-version
)
-
[
2.3 常量池(Constant Pool)
](
#23-常量池constant-pool
)
-
[
2.4 访问标志(Access Flags)
](
#24-访问标志access-flags
)
-
[
2.5 当前类(This Class)、父类(Super Class)、接口(Interfaces)索引集合
](
#25-当前类this-class-父类super-class-接口interfaces
索引集合
)
-
[
2.6 字段表集合(Fields)
](
#26-字段表集合fields
)
-
[
2.7 方法表集合(Methods)
](
#27-方法表集合methods
)
-
[
2.8 属性表集合(Attributes)
](
#28-属性表集合attributes
)
-
[
参考
](
#参考
)
<!-- /TOC -->
<!-- /code_chunk_output -->
# 类文件结构
...
...
@@ -27,11 +29,13 @@ Clojure(Lisp 语言的一种方言)、Groovy、Scala 等语言都是运行
![
java虚拟机
](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/bg/desktop类文件结构概览.png
)
**可以说`.class`文件是不同的语言在 Java 虚拟机之间的重要桥梁,同时也是支持 Java 跨平台很重要的一个原因。**
可以说
`.class`
文件是不同的语言在 Java 虚拟机之间的重要桥梁,同时也是支持 Java 跨平台很重要的一个原因。
## 二 Class 文件结构总结
根据 Java 虚拟机规范,类文件由单个 ClassFile 结构组成:
根据 Java 虚拟机规范,Class 文件通过
`ClassFile`
定义,有点类似 C 语言的结构体。
`ClassFile`
的结构如下:
```
java
ClassFile
{
...
...
@@ -54,41 +58,49 @@ ClassFile {
}
```
下面详细介绍一下 Class 文件结构涉及到的一些组件。
通过分析
`ClassFile`
的内容,我们便可以知道 class 文件的组成。
![](
https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/16d5ec47609818fc.jpeg
)
**Class文件字节码结构组织示意图**
(之前在网上保存的,非常不错,原出处不明):
下面这张图是通过 IDEA 插件
`jclasslib`
查看的,你可以更直观看到 Class 文件结构。
![
类文件字节码结构组织示意图
](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类文件字节码结构组织示意图
.png
)
![
](
https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/java-guide-blog/image-20210401170711475
.png
)
### 2.1 魔数
使用
`jclasslib`
不光可以直观地查看某个类对应的字节码文件,还可以查看类的基本信息、常量池、接口、属性、函数等信息。
下面详细介绍一下 Class 文件结构涉及到的一些组件。
### 2.1 魔数(Magic Number)
```
java
u4
magic
;
//Class 文件的标志
```
每个 Class 文件的头
四个字节称为魔数(Magic Number),它的唯一作用是
**确定这个文件是否为一个能被虚拟机接收的 Class 文件**
。
每个 Class 文件的头
4 个字节称为魔数(Magic Number),它的唯一作用是
**确定这个文件是否为一个能被虚拟机接收的 Class 文件**
。
程序设计者很多时候都喜欢用一些特殊的数字表示固定的文件类型或者其它特殊的含义。
### 2.2 Class 文件版本
### 2.2 Class 文件版本
号(Minor&Major Version)
```
java
u2
minor_version
;
//Class 的小版本号
u2
major_version
;
//Class 的大版本号
```
紧接着魔数的四个字节存储的是 Class 文件的版本号:第五和第六是
**次版本号**
,第七和第八是
**主版本号**
。
紧接着魔数的四个字节存储的是 Class 文件的版本号:第 5 和第 6 位是
**次版本号**
,第 7 和第 8 位是
**主版本号**
。
每当 Java 发布大版本(比如 Java 8,Java9)的时候,主版本号都会加 1。你可以使用
`javap -v`
命令来快速查看 Class 文件的版本号信息。
高版本的 Java 虚拟机可以执行低版本编译器生成的 Class 文件,但是低版本的 Java 虚拟机不能执行高版本编译器生成的 Class 文件。所以,我们在实际开发的时候要确保开发的的 JDK 版本和生产环境的 JDK 版本保持一致。
### 2.3 常量池
### 2.3 常量池
(Constant Pool)
```
java
u2
constant_pool_count
;
//常量池的数量
cp_info
constant_pool
[
constant_pool_count
-
1
];
//常量池
```
紧接着主次版本号之后的是常量池,常量池的数量是
constant_pool_count-1(
**常量池计数器是从1开始计数的,将第0项常量空出来是有特殊考虑的,索引值为0
代表“不引用任何一个常量池项”**
)。
紧接着主次版本号之后的是常量池,常量池的数量是
`constant_pool_count-1`
(
**常量池计数器是从 1 开始计数的,将第 0 项常量空出来是有特殊考虑的,索引值为 0
代表“不引用任何一个常量池项”**
)。
常量池主要存放两大常量:字面量和符号引用。字面量比较接近于 Java 语言层面的的常量概念,如文本字符串、声明为 final 的常量值等。而符号引用则属于编译原理方面的概念。包括下面三类常量:
...
...
@@ -96,11 +108,11 @@ ClassFile {
-
字段的名称和描述符
-
方法的名称和描述符
常量池中每一项常量都是一个表,这
14
种表有一个共同的特点:
**开始的第一位是一个 u1 类型的标志位 -tag 来标识常量的类型,代表当前这个常量属于哪种常量类型.**
常量池中每一项常量都是一个表,这
14
种表有一个共同的特点:
**开始的第一位是一个 u1 类型的标志位 -tag 来标识常量的类型,代表当前这个常量属于哪种常量类型.**
| 类型 | 标志(tag) | 描述 |
| :------------------------------: | :---------: | :--------------------: |
| CONSTANT_utf8_info | 1 | UTF-8
编码的字符串
|
| CONSTANT_utf8_info | 1 | UTF-8
编码的字符串
|
| CONSTANT_Integer_info | 3 | 整形字面量 |
| CONSTANT_Float_info | 4 | 浮点型字面量 |
| CONSTANT_Long_info | 5 | 长整型字面量 |
...
...
@@ -117,9 +129,9 @@ ClassFile {
`.class`
文件可以通过
`javap -v class类名`
指令来看一下其常量池中的信息(
`javap -v class类名-> temp.txt`
:将结果输出到 temp.txt 文件)。
### 2.4 访问标志
### 2.4 访问标志
(Access Flags)
在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为
public 或者 abstract 类型,如果是类的话是否声明为 final
等等。
在常量池结束之后,紧接着的两个字节代表访问标志,这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口,是否为
`public`
或者
`abstract`
类型,如果是类的话是否声明为
`final`
等等。
类访问和属性修饰符:
...
...
@@ -138,7 +150,7 @@ public class Employee {
![
查看类的访问标志
](
https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/查看类的访问标志.png
)
### 2.5 当前类
索引,父类索引与接口
索引集合
### 2.5 当前类
(This Class)、父类(Super Class)、接口(Interfaces)
索引集合
```
java
u2
this_class
;
//当前类
...
...
@@ -147,11 +159,11 @@ public class Employee {
u2
interfaces
[
interfaces_count
];
//一个类可以实现多个接口
```
**类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了 `java.lang.Object` 之外,所有的 java 类都有父类,因此除了 `java.lang.Object` 外,所有 Java 类的父类索引都不为 0。**
类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,由于 Java 语言的单继承,所以父类索引只有一个,除了
`java.lang.Object`
之外,所有的 java 类都有父类,因此除了
`java.lang.Object`
外,所有 Java 类的父类索引都不为 0。
**接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按 `implements` (如果这个类本身是接口的话则是`extends`) 后的接口顺序从左到右排列在接口索引集合中。**
接口索引集合用来描述这个类实现了那些接口,这些被实现的接口将按
`implements`
(如果这个类本身是接口的话则是
`extends`
) 后的接口顺序从左到右排列在接口索引集合中。
### 2.6 字段表集合
### 2.6 字段表集合
(Fields)
```
java
u2
fields_count
;
//Class 文件的字段的个数
...
...
@@ -176,7 +188,7 @@ public class Employee {
![
字段的 access_flag 的取值
](
https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/JVM/image-20201031084342859.png
)
### 2.7 方法表集合
### 2.7 方法表集合
(Methods)
```
java
u2
methods_count
;
//Class 文件的方法的数量
...
...
@@ -197,7 +209,7 @@ Class 文件存储格式中对方法的描述与对字段的描述几乎采用
注意:因为
`volatile`
修饰符和
`transient`
修饰符不可以修饰方法,所以方法表的访问标志中没有这两个对应的标志,但是增加了
`synchronized`
、
`native`
、
`abstract`
等关键字修饰方法,所以也就多了这些关键字对应的标志。
### 2.8 属性表集合
### 2.8 属性表集合
(Attributes)
```
java
u2
attributes_count
;
//此类的属性表中的属性数
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录