JVM虚拟机-Class文件之字段表集合_字段

一、概述

在接口索引集合后面 的就是字段表集合了。字段表(field_info)用于描述接口或者类中声明的变量。字段包括类级变量以及实例级变量,但是不包括在方法内部声明的局部变量。

JVM虚拟机-Class文件之字段表集合_字段_02

二、字段表集合的构成

1.字段计数器

字段表集合是由很多field_info组成的,所以字段表集合的前两个字节表示有多少个字段,占两个字节,16位。

2.field_info

每个field_info的结构如下表所示:

类型    

名称

数量

u2

access_flags

1

u2

name_index

1

u2

descriptor_index

1

u2

attributes_count

1

attribute_info

attributes

attributes_count

JVM虚拟机-Class文件之字段表集合_字段_03

3.access_flags

access_flags为字段修饰符,也称字段访问标志。access_flag占2个字节,16位,它与类中的access_flags项目是非常相似的,包括如下类型:

标志名称

标志值

含义

ACC_PUBLIC

0x00 01

字段是否为public

ACC_PRIVATE

0x00 02

字段是否为private

ACC_PROTECTED

0x00 04

字段是否为protected

ACC_STATIC

0x00 08

字段是否为static

ACC_FINAL

0x00 10

字段是否为final

ACC_VOLATILE

0x00 40

字段是否为volatile

ACC_TRANSTENT

0x00 80

字段是否为transient

ACC_SYNCHETIC

0x10 00

字段是否为由编译器自动产生

ACC_ENUM

0x40 00

字段是否为enum

JVM虚拟机-Class文件之字段表集合_基本数据类型_04

某个字段拥有哪些标志符,就是要用访问标识取|操作:

如0x0001|0x0008为0x0009。

4.name_index和descriptor_index

name_index和descriptor_index,是对常量池的引用,name_index指字段的简单名称,descriptor_index指字段描述符。

descriptor_index描述符用来描述字段的数据类型,基本数据类型用一个大写字符来表示,而对象类型则用字符加L加对象名的全限定名来表示。

标志符

含义

B

基本数据类型byte

C

基本数据类型char

D

基本数据类型double

F

基本数据类型float

I

基本数据类型int

J

基本数据类型long

S

基本数据类型short

Z

基本数据类型boolean

V

基本数据类型void

L

对象类型

对数组类型,每一维将使用一个"["字符来描述.如一个Stirng[][]类型的二维数组,将被记录为:[[Ljava/lang/Stirng,一个整型数组"int []"将被记录为"[I"。

三、实例拆解

定义一个类:

public class HelloWord{

public int i;
private Long l;
protected String[][] arrs;
public Object test(){return null;}
}

 

JVM虚拟机-Class文件之字段表集合_基本数据类型_05

javap -verbose HelloWord.class

public class com.csdn.reader.HelloWord
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#21 // java/lang/Object."<init>":()V
#2 = Class #22 // com/csdn/reader/HelloWord
#3 = Class #23 // java/lang/Object
#4 = Utf8 i
#5 = Utf8 I
#6 = Utf8 l
#7 = Utf8 Ljava/lang/Long;
#8 = Utf8 arrs
#9 = Utf8 [[Ljava/lang/String;
#10 = Utf8 <init>
#11 = Utf8 ()V
#12 = Utf8 Code
#13 = Utf8 LineNumberTable
#14 = Utf8 LocalVariableTable
#15 = Utf8 this
#16 = Utf8 Lcom/csdn/reader/HelloWord;
#17 = Utf8 test
#18 = Utf8 ()Ljava/lang/Object;
#19 = Utf8 SourceFile
#20 = Utf8 HelloWord.java
#21 = NameAndType #10:#11 // "<init>":()V
#22 = Utf8 com/csdn/reader/HelloWord
#23 = Utf8 java/lang/Object
{
public int i;
descriptor: I
flags: ACC_PUBLIC

protected java.lang.String[][] arrs;
descriptor: [[Ljava/lang/String;
flags: ACC_PROTECTED

public com.csdn.reader.HelloWord();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/csdn/reader/HelloWord;

public java.lang.Object test();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aconst_null
1: areturn
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 2 0 this Lcom/csdn/reader/HelloWord;
}

JVM虚拟机-Class文件之字段表集合_基本数据类型_06

四、总结

字段表集合中不会列出从父类或者父接口中继承而来的字段,但有可能列出原来Java代码中不存在的字段和方法,譬如在内部类中为了保持对外部类的访问性,会自动添加指向外部类实例的字段。

另外,在Java语言中字段是无法重载的,两个字段的数据类型,修饰符不管是否相同,都必须使用不一样的名称,但是对于字节码来讲,如果连个字段的描述符不一致,那字段重名就是合法的。