[jvm解析系列][七]字段表集合volatilevolatile和属性表集合,你的变量该如何存储?
Posted 胖子程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[jvm解析系列][七]字段表集合volatilevolatile和属性表集合,你的变量该如何存储?相关的知识,希望对你有一定的参考价值。
上段我们说到一个类的基本构成,今天我们来讲一下类的内部结构。类的内部一般情况下由类的成员变量(类字段),方法和内部类等构成。
1、字段表:
不好意思我们这一次需要先上字段表的内容然后一个一个讲解,不能像前面那样像设计者一样一个一个的推出来了,主要原因还是字段表里包含了属性表。
access_flags
还记得我们在上一篇里讲的,在类的继承关系之后应该就是field_info他主要描述接口或者类中声明的变量。field包括类和实例级变量(声明在方法外的变量)。那么我们想一下一个成员变量应该有什么?我们平时这样声明一个变量。如:private int a = 0;所以,首先要有的应该是一个作用域(public private protected),接下来是一个int,这个被叫做字段数据类型(也就是int或者其他类型,还有对象,数组)。当然有时候我们还会申请这样一个变量:public static final int a =0;那么我们应该还有一个用来表示他是否是final的变量,被叫做可变性。还有一个static变量需要描述。当然不能缺少了一个enum类型的变量,有时候我们还会见到一些不常见的修饰符,如volatile、transient。
volatile关乎到jvm的变量赋值问题,在jvm中,a++这个方法不是每次都要去堆内直接操作内存的,他被编译成了四个部分
1、把内存里的变量复制到自己的方法栈内
2、进行完修改,这里有赋值和加两部份
3、再赋值回去。这样如果有A,B两个线程同时访问变量a,并且同时修改+1,在返回堆中的时候a并不会+2而是+1。
所以volatile变量声明的变量可以保证每次读取的数据都是最新数据,但是注意,不可以保证原子性。
除此之外volatile还可以保证指令重排优化,这里我们以后会讲。
2、transient,在序列化的时候,被transient修饰的变量不参与序列化,默认不被transient修饰。
综上所述,一个字段表应该包括字段的作用域,static,final,volatile,transient,是否由编译器自动生成的,字段是否enum。如下图所示
name_index,descriptor_index
前面我们已经说过了,这个位置应该是一个field_info的表,既然是一个表就不可能仅仅只有上面一个最多u2类型的字段构成。所以除此之外我们还需要字段的简单名称和描述符。
1、简单名称就是如int a;a就是简单名称
2、描述符:描述符主要用来描述字段的数据类型、方法的参数列表和返回值。这一块不在JVM范围内,后面会在杂项中补充。
attributes
最后也就是一个需要细细讲解的部分,属性,在Class文件,字段表,放发表中都可以携带自己的属性表集合。
一个属性应该是下列这样的结构:
attribute_name_index 代表了一个常量池关于属性名称的索引。
而info代表了每一个属性的内容,我们并不强求info的长度,我们只需要一个u4类型的length来表示这个属性到底有多长就可以了。
而一个字段表内可以声明如下的属性:
关于每一个属性表的具体结构,我们会到放到下一章,因为方法表中也有属性,综合在一起讲一些比较常见的属性。
以上是关于[jvm解析系列][七]字段表集合volatilevolatile和属性表集合,你的变量该如何存储?的主要内容,如果未能解决你的问题,请参考以下文章