(转)《Java虚拟机原理图解》1.4 class文件中的字段表集合--field字段在class文件中是怎样组织的

来源:互联网 发布:java高级流和低级流 编辑:程序博客网 时间:2024/05/21 09:36

原文地址:http://blog.csdn.net/luanlouis/article/details/41046443


0.前言

         了解JVM虚拟机原理是每一个Java程序员修炼的必经之路。但是由于JVM虚拟机中有很多的东西讲述的比较宽泛,在当前接触到的关于JVM虚拟机原理的教程或者博客中,绝大部分都是充斥的文字性的描述,很难给人以形象化的认知,看完之后感觉还是稀里糊涂的。

         感于以上的种种,我打算把我在学习JVM虚拟机的过程中学到的东西,结合自己的理解,总结成《Java虚拟机原理图解》 这个系列,以图解的形式,将抽象的JVM虚拟机的知识具体化,希望能够对想了解Java虚拟机原理的的Java程序员 提供点帮助。


读完本文,你将会学到:

1、类中定义的field字段是如何在class文件中组织的

2、不同的数据类型在class文件中是如何表示的

3、static final类型的field字段的初始化赋值问题

1.概述

     字段表集合是指由若干个字段表(field_info)组成的集合。对于在类中定义的若干个字段,经过JVM编译成class文件后,会将相应的字段信息组织到一个叫做字段表集合的结构中,字段表集合是一个类数组结构,如下图所示:

注意:这里所讲的字段是指在类中定义的静态或者非静态的变量,而不是在类中的方法内定义的变量。请注意区别。

比如,如果某个类中定义了5个字段,那么,JVM在编译此类的时候,会生成5个字段表(field_info)信息,然后将字段表集合中的字段计数器的值设置成5,将5个字段表信息依次放置到字段计数器的后面。

2. 字段表集合在class文件中的位置

字段表集合紧跟在class文件的接口索引集合结构的后面,如下图所示:


3. Java中的一个Field字段应该包含那些信息?------字段表field_info结构体的定义    

  

    针对上述的字段表示,JVM虚拟机规范规定了field_info结构体来描述字段,其表示信息如下:

下面我将一一讲解FIeld_info的组成元素:访问标志(access_flags)名称索引(name_index)描述索引(descriptor_index)属性表集合

 4. field字段的访问标志

     如上图所示定义的field_info结构体,field字段的访问标志(access_flags)占有两个字节,它能够表述的信息如下所示:

举例:如果我们在某个类中有定义field域:private static String str;,那么在访问标志上,第15ACC_PRIVATE和第13ACC_STATIC标志位都应该为1。fieldstr的访问标志信息应该是如下所示:


如上图所示,str字段的访问标志的值为0x000A,它由两个修饰符ACC_PRIVATEACC_STATIC组成。

根据给定的访问标志(access_flags),我们可以通过以下运算来得到这个域有哪些修饰符:

上面列举的str字段的访问标志的值为000A,那么分别域上述的标志符的特征值取&,结果为1的只有ACC_PRIVATEACC_STATIC,所以该字段的标志符只有有ACC_PRIVATEACC_STATIC



5. 字段的数据类型表示和字段名称表示

class文件对数据类型的表示如下图所示:



field字段名称,我们定义了一个形如private static String strfield字段,其中"str"就是这个字段的名称。

class文件将字段名称和field字段的数据类型表示作为字符串存储在常量池中。在field_info结构体中,紧接着访问标志的,就是字段名称索引和字段描述符索引,它们分别占有两个字节,其内部存储的是指向了常量池中的某个常量池项的索引,对应的常量池项中存储的字符串,分别表示该字段的名称和字段描述符。


6.属性表集合-----静态field字段的初始化

在定义field字段的过程中,我们有时候会很自然地对field字段直接赋值,如下所示:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. public static final int MAX=100;  
  2. public  int count=0;  
对于虚拟机而言,上述的两个field字段赋值的时机是不同的:
  •        对于非静态(即无static修饰)的field字段的赋值将会出现在实例构造方法<init>()
  •        对于静态的field字段,有两个选择:1、在静态构造方法<cinit>()中进行;2 、使用ConstantValue属性进行赋值
Sun javac编译器对于静态field字段的初始化赋值策略

目前的Sun javac编译器的选择是:如果使用finalstatic同时修饰一个field字段,并且这个字段是基本类型或者String类型的,那么编译器在编译这个字段的时候,会在对应的field_info结构体中增加一个ConstantValue类型的结构体,在赋值的时候使用这个ConstantValue进行赋值;如果该field字段并没有被final修饰,或者不是基本类型或者String类型,那么将在类构造方法<cinit>()中赋值。

对于上述的public static final init MAX=100;   javac编译器在编译此field字段构建field_info结构体时,除了访问标志、名称索引、描述符索引外,会增加一个ConstantValue类型的属性表。


7.实例解析:

定义如下一个简单的Simple类,然后通过查看Simple.class文件内容并结合javap -v Simple 生成的常量池内容,分析str field字段的结构:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. package com.louis.jvm;  
  2.   
  3. public class Simple {  
  4.   
  5.     private  transient static final String str ="This is a test";  
  6. }  


注:

1. 字段计数器中的值为0x0001,表示这个类就定义了一个field字段
2. 字段的访问标志0x009A,二进制是00000000 10011010,即第9、12、13、15位标志位为1,这个字段的标志符有:ACC_TRANSIENT、ACC_FINAL、ACC_STATIC、ACC_PRIVATE;

3. 名称索引中的值为0x0005,指向了常量池中的第5项,为“str”,表明这个field字段的名称是str

4. 描述索引中的值为0x0006,指向了常量池中的第6项,为"Ljava/lang/String;",表明这个field字段的数据类型是java.lang.String类型;

5.属性表计数器中的值为0x0001,表明field_info还有一个属性表;

6.属性表名称索引中的值为0x0007,指向常量池中的第7项,为“ConstantValue”,表明这个属性表的名称是ConstantValue,即属性表的类型是ConstantValue类型的;

7.属性长度中的值为0x0002,因为此属性表是ConstantValue类型,它的值固定为2

8.常量值索引 中的值为0x0008,指向了常量池中的第8项,为CONSTANT_String_info类型的项,表示“This is a test” 的常量。在对此field赋值时,会使用此常量对field赋值。







作者的话

    本文是《Java虚拟机原理图解》系列的其中一篇,如果您有兴趣,请关注该系列的其他文章~

   觉得本文不错,顺手点个赞哦~~您的鼓励,是我继续分享知识的强大动力!

    

 

-----------------------------------------------------------------------------------------------------------------------------------------

                                                                              本文源自  http://blog.csdn.net/luanlouis/,如需转载,请注明出处,谢谢!
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 复制文件过程中自己卡住了怎么办 电脑卡住了怎么办 鼠标也点不动 善领wifi连上网不能用怎么办 苹果手机软件更新后网速太慢怎么办 装了固态硬盘开机还慢怎么办 华为荣耀8青春版玩游戏卡怎么办 光猫自带wifi网络很差怎么办 侠盗猎车手自由城之章卡退怎么办? 夏天带头盔晃眼睛太厉害怎么办 别人把钱误转我卡上我怎么办? 家里预留的的网线太短怎么办 电信路由器坏了网线接口断了怎么办 数据线充手机的接头处断了怎么办 新买的小米手环充不进去电怎么办 绝地求生手游被队友故意炸死怎么办 一加3t屏幕开了怎么办? 孕妇吃了8个杏怎么办啊 洗碗盆落水器垫子密封不好怎么办? 手剥橙子剥的特别疼怎么办? 经常带对讲机的耳麦耳朵痛怎么办 公安检查遇到穿便装的军人怎么办 cf幽灵鬼呼吸辅军训刘海怎么办助 眼睛被等离子切割器的光烤了怎么办 玩王者的时候屏幕竖着了该怎么办 铝合金门双包门套比墙的厚了怎么办 磁共振检查后发现带金属了怎么办 贴了乳贴过免痒怎么办 yy别人听见我打游戏的声音怎么办 微信的聊天记录发错邮箱怎么办 百度云盘文件有违规内容怎么办 天籁一键启动钥匙没电怎么办 中兴手机系统界面已停止运行怎么办 怎么办可以复制成不关联的文档 希捷400g硬盘电机不转怎么办 金立手机微信语音播放失败怎么办 手机4g网络变2g怎么办 生存战争2吃了腐烂的食物后怎么办 古筝调音 d的显示为b怎么办 消防建审没有原有的结构图纸怎么办 生石灰弄到脸上用水洗后发热怎么办 吃了没熟的鹅肝怎么办