JVM 类结构

1概述

1.1类文件格式不是必须存在于文件里。

1.2多字节数据项必须严格按照大端在前(big-endian)顺序进行存储(Multibyte data items are always stored in big-endian order,where the high bytes come first)

1.3 Class文件是一组以8字节为基础单位的二进制流,各个数据项严格按照顺序紧凑排列,没有任何分隔符

1.4Class文件格式采用一种类似C语言结构体的伪结构(This chapter presents the class file format using pseudostructures written in a C-like structure notation),只有两种数据类型:无符号数(unsigned)和表(table)

1.5无符号数是基本的数据类型,可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串值,以u1,u2,u4,u8来分别代表1个字节,2个字节,4个字节,8个字节

1.6表由多个无符号数或其他表作为数据项构成的复合数据类型

1.7当描述同一类型但数量不定的多个数据时,经常会使用一个前置的容量计数器加若干个连续的数据项的形式,这时候称这一系列连续的某一类型的数据为某一类型的集合

 

2、类结构元素

类型

数量

说明

u4

1

魔数(magic),确定是否为虚拟机所接受的类文件,固定值为0xCAFEBABE

u2

1

副版本号(minor_version)

1、主版本号为45-55时,副版本号可以为任何值

2、从主版本号56(jdk12)开始,副版本号必须为0或65535

3、当副版本号为65535时,为预览版

u2

1

主版本号(major_version),

1、值从45开始

2、即使文件格式无任何变化,虚拟机也必须拒绝执行类主版本号超过虚拟机版本号的文件。

u2

1

constant_pool_count;常量池计数器

cp_info

constant_pool[constant_pool_count-1]

常量池

1、是一种表结构

2、以1constant_pool_count-1为索引

3、第一个字节作为类型标记,这个字节称为标签字节(tag byte)

4、主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)

5、通用格式:

cp_info {

u1 tag;

u1 info[];

}

u2

1

access_flags;访问标志,

1、一种由标志构成的掩码

The value of the access_flags item is a mask of flags used to denote access permissions to and properties of this class or interface

2、取值以及含义参考本章第4节

3、没有使用到的标志位都为0

u2

1

this_class;类索引

1、取值为常量池有效的索引值

2、常量池中索引处的成员必须为CONSTANT_Class_info类型

u2

1

super_class;父类索引

1、Java不允许多重继承,所以父类索引只有一个

2、取值要么为0,要么是常量池中某个有效索引值

3、当值为0,此类只能用于表示Object类

4、当值不为0,常量池中索引处的成员必须为CONSTANT_Class_info类型

5、所有父类的access_flags,均不能带有ACC_FINAL标志

Neither the direct superclass nor any of its superclasses may have the ACC_FINAL flag set in the access_flags item of its ClassFile structure.

u2

1

interfaces_count;接口索引计数器,如果没有接口,则取值0

u2

interfaces[interfaces_count]

接口集合

1、每个元素值都是常量池中某个有效索引值

2、按implements关键字后面的接口,从左到右排列

u2

1

fields_count;字段计数器

field_info

fields[fields_count]

字段表

1、每个成员都是field_info结构,参考2.4

2、包括类变量和实例变量

3、不包括方法内声明的局部变量

4、不包括从父类或父接口继承的那些字段

u2

1

methods_count;方法计数器

method_info

methods[methods_count]

1、每个成员都是method_info结构,参考本章第7节

2、方法表只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法

3、支持方法访问权限(access_flags)既不是ACC_NATIVE又不是ACC_ABSTRACT

u2

1

attributes_count;属性计数器

attribute_info

attributes[attributes_count]

1、每个成员都是attribute_info结构,参考2.6

 

3、常量池(constant_pool)

3.1基本格式

字段

类型

说明

tag

u1

类型

info[]

u1

 

 

3.2常量池类型(tag)

类型

tag

类文件版本

首次javaSE版本

说明

CONSTANT_Utf8

1

45.3

1.0.2

UTF-8编码的字符串

CONSTANT_Integer

3

45.3

1.0.2

整型字面量

CONSTANT_Float

4

45.3

1.0.2

浮点型字面量

CONSTANT_Long

5

45.3

1.0.2

长整型字面量

CONSTANT_Double

6

45.3

1.0.2

双精度浮点型字面量

CONSTANT_Class

7

45.3

1.0.2

类或接口的索引

CONSTANT_String

8

45.3

1.0.2

字符串类型字面量

CONSTANT_Fieldref

9

45.3

1.0.2

字段的符号引用

CONSTANT_Methodref

10

45.3

1.0.2

类中方法的符号引用

CONSTANT_InterfaceMethodref

11

45.3

1.0.2

接口中方法的符号引用

CONSTANT_NameAndType

12

45.3

1.0.2

字段或方法的部分符号引用

CONSTANT_MethodHandle

15

51

7

表示方法具柄

CONSTANT_MethodType

16

51

7

方法类型

CONSTANT_InvokeDynamic

18

51

7

表示一个动态方法调用点

CONSTANT_Module

19

53

9

表示一个模块

CONSTANT_Package

20

53

9

表示一个模块中开放或者导出的包

CONSTANT_Dynamic

17

55

11

表示一个动态计算常量

 

3.3常量池数据类型的结构

 

类型

字段

类型

CONSTANT_Utf8

tag

u1

length

u2

bytes[]

u1

CONSTANT_Integer

tag

u1

bytes

u4

CONSTANT_Float

tag

u1

bytes

u4

CONSTANT_Long

tag

u1

high_bytes

u4

low_bytes

u4

CONSTANT_Double

tag

u1

high_bytes

u4

low_bytes

u4

CONSTANT_Class

tag

u1

name_index

u2

CONSTANT_String

tag

u1

string_index

u2

CONSTANT_Fieldref

tag

u1

class_index

u2

name_and_type_index

u2

CONSTANT_Methodref

tag

u1

class_index

u2

name_and_type_index

u2

CONSTANT_InterfaceMethodref

tag

u1

class_index

u2

name_and_type_index

u2

CONSTANT_NameAndType

tag

u1

name_index

u2

descriptor_index

u2

CONSTANT_MethodHandle

tag

u1

reference_kind

u2

reference_index

u2

CONSTANT_MethodType

tag

u1

descriptor_index

u2

CONSTANT_InvokeDynamic

tag

u1

bootstrap_method_attr_index

u2

name_and_type_index

u2

CONSTANT_Module

tag

u1

name_index

u2

CONSTANT_Package

tag

u1

name_index

u2

CONSTANT_Dynamic

tag

u1

bootstrap_method_attr_index

u2

name_and_type_index

u2

 

 

4类访问标志(access_flags)

标志

说明

ACC_PUBLIC

0x0001

public

ACC_FINAL

0x0010

final,不能与ACC_ABSTRACT同时设置

ACC_SUPER

0x0020

是否使用invokespecial指令的新语义,因为invokespecial指令在jdk1.0.2以后做了改变,所以在jdk1.0.2之后,这里都为真

ACC_INTERFACE

0x0200

接口,设置了此值,ACC_ABSTRACT必须同时设置

ACC_FINAL, ACC_SUPER, ACC_ENUM和 ACC_MODULE,必须不能设置

ACC_ABSTRACT

0x0400

抽象类,不能实例化

ACC_SYNTHETIC

0x1000

标志该类或接口是由编译器生成

ACC_ANNOTATION

0x2000

声明为注解,同时必须设置ACC_SYNTHETIC

ACC_ENUM

0x4000

声明为枚举

ACC_MODULE

0x8000

声明为模块,如果这个值被设置,则不能有其他标志被设置

If the ACC_MODULE flag is set in the access_flags item, then no other flag in the access_flags item may be set

 

 

5字段表结构(field_info)

5.1基础结构

字段

类型

说明

access_flags

u2

访问标志,参考2.4.2

name_index

u2

字段简单名称,指向常量池一个CONSTANT_Utf8_info值的索引

descriptor_index

u2

字段的描述符,指向常量池一个CONSTANT_Utf8_info值的索引

attributes_count

u2

参考2.7

attributes[attributes_count]

attribute_info

参考2.7

 

5.2字段访问标志

标志

说明

ACC_PUBLIC

0x0001

public

ACC_PRIVATE

0x0002

private

ACC_PROTECTED

0x0004

protected

ACC_STATIC

0x0008

static

ACC_FINAL

0x0010

final

ACC_VOLATILE

0x0040

volatile

ACC_TRANSIENT

0x0080

transient

ACC_SYNTHETIC

0x1000

标志该字段是由编译器生成,如果字段存在这个标志,则不能有其他任何访问标志

ACC_ENUM

0x0001

枚举

a ACC_PUBLIC、ACC_PRIVATE、ACC_PROTECTED三选一

b ACC_FINAL、ACC_VOLATILE二选一

c接口中的字段必须有ACC_PUBLIC,ACC_STATIC,ACC_FINAL,三个标志

 

6方法结构(method_info)

6.1基础结构

字段

类型

说明

access_flags

u2

访问标志,参考本章6.2

name_index

u2

字段简单名称,指向常量池一个CONSTANT_Utf8_info值的索引,必须是有效的非限定名称,或者<init>,或者<clinit>

descriptor_index

u2

字段的描述符,指向常量池一个CONSTANT_Utf8_info值的索引,

1、当是类的<init>方法,必须描述为void方法

2、当类名是<clinit>,必须描述为void方法,且jdk7以后,此方法无参数

attributes_count

u2

参考2.7

attributes[attributes_count]

attribute_info

参考2.7

 

 

6.2方法访问标志

标志

说明

ACC_PUBLIC

0x0001

public

ACC_PRIVATE

0x0002

private

ACC_PROTECTED

0x0004

protected

ACC_STATIC

0x0008

static,jdk7以后<clinit>方法必须有此标志

ACC_FINAL

0x0010

final

ACC_SYNCHRONIZED

0x0020

synchronized

ACC_BRIDGE

0x0040

桥接方法,为了泛型方法兼容jdk1.5以前版本,编译器自动生成

ACC_VARARGS

0x0080

有可变长参数的标志

ACC_NATIVE

0x0100

native

ACC_ABSTRACT

0x0400

abstract

ACC_STRICT

0x0800

 

ACC_SYNTHETIC

0x1000

 

a ACC_PUBLIC, ACC_PRIVATE,ACC_PROTECTED 必须三选一

b jdk8以前,接口的方法必须有ACC_PUBLIC 和ACC_ABSTRACT标志

c jdk8以及以后,接口的方法必须ACC_PUBLIC , ACC_PRIVATE二选一

d 方法如果标记了ACC_ABSTRACT,则不能有ACC_PRIVATE, ACC_STATIC, ACC_FINAL,ACC_SYNCHRONIZED, ACC_NATIVE, ACC_STRICT标记

e实例的初始化方法只能ACC_PUBLIC, ACC_PRIVATE,ACC_PROTECTED三选一,以及ACC_VARARGS, ACC_STRICT, ACC_SYNTHETIC可选,不能有其他标志

f实例或接口的方法被隐式调用,只能设置ACC_STATIC 和 ACC_STRICT标志

 

 

7属性结构(attribute_info)

7.1基本结构

字段

类型

说明

attribute_name_index

u2

指向常量池一个CONSTANT_Utf8_info值的索引

attribute_length

u4

属性长度,长度不包括自身和attribute_name_index的长度

info[attribute_length]

u1

 

 

7.2属性类型

属性

位置

首次版本

ConstantValue

field_info

45.3

Code

method_info

45.3

Exceptions

method_info

45.3

SourceFile

classFile

45.3

LineNumberTable

code

45.3

LocalVariableTable

code

45.3

InnerClasses

classFile

45.3

Synthetic

classFile

field_info

method_info

45.3

Deprecated

classFile

field_info

method_info

45.3

EnclosingMethod

classFile

49

Signature

classFile

field_info

method_info

49

SourceDebugExtension

classFile

49

LocalVariableTypeTable

code

49

RuntimeVisibleAnnotations

classFile

field_info

method_info

49

RuntimeInvisibleAnnotations

classFile

field_info

method_info

49

RuntimeVisibleParameterAnnotations

method_info

49

RuntimeInvisibleParameterAnnotations

method_info

49

AnnotationDefault

method_info

49

StackMapTable

code

50

BootstrapMethods

classFile

51

RuntimeVisibleTypeAnnotations

classFile

field_info

method_info

code

52

RuntimeInvisibleTypeAnnotations

classFile

field_info

method_info

code

52

MethodParameters

method_info

52

Module

classFile

53

ModulePackages

classFile

53

ModuleMainClass

classFile

53

NestHost

classFile

55

NestMembers

classFile

55

 

7.3属性类型结构

posted @ 2020-05-31 19:05  adeveloper  阅读(243)  评论(0编辑  收藏  举报