From c25a0c100028b89a426c7c69ea7151542da88dd8 Mon Sep 17 00:00:00 2001 From: Omooo <869759698@qq.com> Date: Thu, 25 Apr 2019 21:18:29 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20finsh=20=E5=B8=B8=E9=87=8F?= =?UTF-8?q?=E6=B1=A0=E5=8F=8A=E7=9B=B8=E5=85=B3=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 +- .../属性介绍.md | 29 +++++ .../常量池及相关内容.md | 104 +++++++++++++++++- 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 blogs/JVM/深入理解 Class 文件格式/属性介绍.md diff --git a/README.md b/README.md index c3c030e..c59fd4d 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,13 @@ Android Notes ##### JVM、ART 相关 -[Class 文件格式总览](https://github.com/Omooo/Android-Notes/blob/master/blogs/JVM/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%20Class%20%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/Class%20%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E6%80%BB%E8%A7%88.md) +Class 文件格式 + +​ [Class 文件格式总览](https://github.com/Omooo/Android-Notes/blob/master/blogs/JVM/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%20Class%20%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F/Class%20%E6%96%87%E4%BB%B6%E6%A0%BC%E5%BC%8F%E6%80%BB%E8%A7%88.md) + +​ [常量池及相关内容](https://github.com/Omooo/Android-Notes/blob/master/blogs/JVM/深入理解 Class 文件格式/常量池及相关内容.md) + +​ [属性介绍] ##### 性能优化 @@ -80,7 +86,9 @@ Android Notes #### Framework -[Android 系统架构]() +[Android 系统架构](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Framework/Android 系统架构.md) + +[Android 系统启动](https://github.com/Omooo/Android-Notes/blob/master/blogs/Android/Framework/Android 系统启动.md) #### Java 基础 diff --git a/blogs/JVM/深入理解 Class 文件格式/属性介绍.md b/blogs/JVM/深入理解 Class 文件格式/属性介绍.md new file mode 100644 index 0000000..9ce9837 --- /dev/null +++ b/blogs/JVM/深入理解 Class 文件格式/属性介绍.md @@ -0,0 +1,29 @@ +--- +属性介绍 +--- + +#### 目录 + +1. 属性概述 +2. Code 属性 +3. LineNumberTable 属性 +4. LocalVariableTable 属性 + +#### 属性概述 + +属性是 Class 文件的重要组成部分。和常量池类似,属性也分为很多类型,在 Java 虚拟机规范中,属性可用 attribute_info 数据结构伪代码表示: + +``` +attribute_info{ + + //属性名称,指向常量池中 Utf8 常量项的索引 + u2 attribute_name_index; + + //该属性具体内容的长度,即下面 info 数组的长度 + u4 attribute_length; + + //属性具体内容 + u1 info[attribute_length]; +} +``` + diff --git a/blogs/JVM/深入理解 Class 文件格式/常量池及相关内容.md b/blogs/JVM/深入理解 Class 文件格式/常量池及相关内容.md index 657be02..dea4595 100644 --- a/blogs/JVM/深入理解 Class 文件格式/常量池及相关内容.md +++ b/blogs/JVM/深入理解 Class 文件格式/常量池及相关内容.md @@ -6,6 +6,8 @@ 1. 常量项的类型和关系 2. 信息描述规则 +3. field_info 和 method_info +4. access_flags 介绍 #### 常量项的类型和关系 @@ -134,4 +136,104 @@ CONSTANT_Float_info{ #### 信息描述规则 -根据 Java 虚拟机规范,如何用字符串来描述成员变量、成员函数是有讲究的, \ No newline at end of file +根据 Java 虚拟机规范,如何用字符串来描述成员变量、成员函数是有讲究的,这些规则主要集中在数据类型、成员变量和成员函数的描述规则。包括 + +- 数据类型的描述规则 +- 成员变量的描述规则,即 Field Descriptor +- 成员函数的描述规则,即 Method Descriptor + +##### 数据类型的描述规则 + +| 类型 | 描述 | +| ------- | ------------------ | +| byte | B | +| char | C | +| double | D | +| float | F | +| int | I | +| long | J | +| short | S | +| boolean | B | +| String | Ljava/lang/String; | +| int[] | [I | + +##### 成员变量描述规则 + +就是类似上面的数据类型。 + +##### 成员函数描述规则 + +和成员变量略有不同的是,一个成员函数(Method Description)的描述需要包含返回值及参数的数据类型。 + +比如,对于 System.out.print(String str) 函数,它的 Method Description 是: + +```java +(Ljava/lang/String;)V +``` + +Method Description 不包含函数名,这样做的目的其实也是为了节省空间,因为很多函数可能名字不同,但是它们的 Method Description 是一样的。 + +#### field_info 和 method_info + +它们的数据结构伪代码如下: + +```java +field_info{ + u2 access_flags; + u2 name_index; + u2 descriptor_index; + u2 attributes_count; + attribute_info attributes[attributes_count]; +} + +method_info{ + u2 access_flags; + u2 name_index; + u2 descriptor_index; + u2 attributes_count; + attribute_info attributes[attributes_count]; +} +``` + +- access_flags + + 访问标志 + +- name_index + + 指向成员变量或成员函数的名字的 Utf8_info 常量项。 + +- descriptor_index + + 也指向 Utf8_info 常量项,其内容分别是描述成员变量的 FieldDescriptor 和描述成员函数的 MethodDescriptor。 + +- attributes + + 为属性信息,成员域和成员函数都包含若干属性。 + +既然 method_info 描述的是一个成员函数,那么这个函数对应的代码经过编译后得到的 Java 字节码存储在什么地方呢? + +其实存储在属性中。 + +#### access_flags + +access_flags 其实就是访问修饰符,如下: + +| 标识位 | 说明 | +| ---------------- | -------------------- | +| ACC_PUBLIC | public | +| ACC_FINAL | final | +| ACC_INTERFACE | interface | +| ACC_ABSTRACT | abstract | +| ACC_ANNOTATION | annotation | +| ACC_ENUM | 枚举类型 | +| ACC_PROTECT | protect | +| ACC_STATIC | static | +| ACC_VOLATILE | volatile | +| ACC_TRANSIENT | transient | +| ACC_NATIVE | native | +| ACC_VARARGS | 可变长参数个数的函数 | +| ACC_SYNCHRONIZED | synchronized | +| ... | ... | + +之前写过,关于 synchronized 方法的实现原理,是在方法前面加上 ACC_SYNCHRONIZED 的标识位,原本我以为只有 synchronized 方法会有这种标识位,其他一些访问修饰符都没有,看来还是 too young too simple~ \ No newline at end of file