class字节码结构(三)(字段集合的结构)
《Java虚拟机原理图解》1.4 class文件中的字段表集合--field字段在class文件中是怎样组织的
字段区:包括了字段计数器和字段数据区:
字段是指在类中定义的静态或者非静态的全局变量,而不是在类中的方法内定义的局部变量。
Field字段应该包含的信息:
field字段的访问标志(access_flags)占有两个字节16位,通过每一位来表示不同的特征
字段的数据类型表示:
field_info结构体中,存储的是指向了常量池中该字段的名称和字段描述符的索引。
属性表集合:
针对final修饰的字段会有一个ConstantValue属性,将字段的值关联起来,存放的是指向常量池的字段值的索引。
特别注意的是:
- ,为什么会存在多个ConstantValue(有点奇怪,要么就是上图画错了,应该是字段存在多个属性,而不是多个constantValue)。
- ,还有就是有个说法只有static的字段 才有这个属性,但是我测试,只有final修饰的才有这个属性。
我的测试:(只有final有constantValue属性)
- 代码的全局变量:
- int aa=;
- static int aaa=;
- final int b=;
- static final int c=;
- 字节码字段区域如下:(javap -v xxx类名xxx打开 显示的效果,不是索引,可能和虚拟机版本也有关系吧)
- int aa;
- descriptor: I
- flags:
- static int aaa;
- descriptor: I
- flags: ACC_STATIC
- final int b;
- descriptor: I
- flags: ACC_FINAL
- ConstantValue: int
- static final int c;
- descriptor: I
- flags: ACC_STATIC, ACC_FINAL
- ConstantValue: int
关于字段赋值的时机:
- public static final int MAX=;
- public int count=;
- a,对于非静态的field字段的赋值将会出现在实例构造方法<init>()中
- b,对于静态的field字段,有两个选择:
- 、在静态构造方法<cinit>()中进行;
- 、使用ConstantValue属性进行赋值
编译器对于静态field字段的初始化赋值策略:
- 如果final和static同时修饰一个字段,并且这个字段是基本类型或者String类型的,
那么编译器在编译这个字段的时候,会在对应的field_info结构体中增加一个ConstantValue类型的结构体,在赋值的时候使用这个ConstantValue进行赋值;- 如果该field字段并没有被final修饰,或者不是基本类型或者String类型,那么将在类构造方法中赋值。
- 感觉有点问题:测试结果是有final就有ConstantValue属性。
一个例子:
- public class Simple {
- private transient static final String str ="This is a test";
- }
总结:对于字段区域是对接口和类的全局字段的描述,将字段各部分关联起来。
最后有一个疑问:对于不是final修饰的字段,常量池没有存放它的值,字段数据区域也没有存放。程序运行后怎么得到它的值的。
只能看接下,构造方法是否有存放了。
补充:对于全局变量的值是被编译在构造器中赋值的:
例子:Java字节码浅析(—)
- public class SimpleClass {
- public int simpleField = ;
- }
字节码中字段信息:
- public int simpleField;
- Signature: I
- flags: ACC_PUBLIC
字节的构造方法中赋值:
- public SimpleClass();
- Signature: ()V
- flags: ACC_PUBLIC
- Code:
- stack=, locals=, args_size=
- : aload_0
- : invokespecial # // Method java/lang/Object."<init>":()V
- : aload_0
- : bipush
- : putfield # // Field simpleField:I
- : return
- aload_0
- 从局部变量数组中加载一个对象引用到操作数栈的栈顶。尽管这段代码看起来没有构造方法,
- 但是在编译器生成的默认的构造方法里,就会包含这段初始化的代码。第一个局部变量正好是this引用,
- 于是aload_0把this引用压到操作数栈中。aload_0是aload_指令集中的一条,这组指令会将引用加载到操作数栈中。
- n对应的是局部变量数组中的位置,并且也只能是0,,,。还有类似的加载指令,它们加载的并不是对象引用,
- 比如iload_,lload_,fload_,和dload_, 这里i代表int,l代表long,f代表float,d代表double。
- 局部变量的在数组中的位置大于3的,得通过iload,lload,fload,dload,和aload进行加载,
- 这些指令都接受一个操作数,它代表的是要加载的局部变量的在数组中的位置。
- invokespecial
- 这条指令可以用来调用对象实例的构造方法,私有方法和父类中的方法。
- 它是方法调用指令集中的一条,其它的还有invokedynamic, invokeinterface, invokespecial, invokestatic, invokevirtual.
- 这里的invokespecial指令调用的是父类也就是java.lang.Object的构造方法。
- bipush 它是用来把一个字节作为整型压到操作数栈中的,在这里100会被压到操作数栈里。
- putfield
- 它接受一个操作数,这个操作数引用的是运行时常量池里的一个字段,在这里这个字段是simpleField。
- 赋给这个字段的值,以及包含这个字段的对象引用,在执行这条指令的时候,都 会从操作数栈顶上pop出来。
- 前面的aload_0指令已经把包含这个字段的对象压到操作数栈上了,而后面的bipush又把100压到栈里。
- 最后putfield指令会将这两个值从栈顶弹出。执行完的结果就是这个对象的simpleField这个字段的值更新成了100。
class字节码结构(三)(字段集合的结构)的更多相关文章
- JVM 字节码(三)异常在字节码中的处理(catch 和 throws)
JVM 字节码(三)异常在字节码中的处理(catch 和 throws) 在 ClassFile 中到底是如何处理异常的呢? 一.代码块异常 catch catch 中的异常代码块在异常是如何处理的呢 ...
- Jpa/Hibernate 字节码增强:字段延迟加载
JPA提供了@Basic注解,实现延迟加载字段的功能,如下: @Basic(fetch = FetchType.LAZY) @Column(name = "REMARK_CONTENT&qu ...
- 图解JVM字节码执行引擎之栈帧结构
一.执行引擎 “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...
- java虚拟机5 字节码
java字节码本质是java程序的格式化表示,便于机器处理.所以他是java程序的另一种表示,java程序包含的信息他都包含并且更加结构化. java虚拟机字节码格式: magic 魔数,标识该文件是 ...
- JVM 字节码执行实例分析
前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...
- Java反射获取字节码以及判断类型
一.获取类的字节码的三种方法: 1.使用Class.class Class<?> c1=String.class; 2.使用实例.getClass() String s= Clas ...
- class字节码结构(四)(方法集合的结构)
<Java虚拟机原理图解>1.5. class文件中的方法表集合--method方法在class文件中是怎样组织的 一个类有多个方法,所以方法肯定是一个集合. 目标是: 1,了解方法在字节 ...
- java动态代理——字段和方法字节码的基础结构及Proxy源码分析三
前文地址:https://www.cnblogs.com/tera/p/13280547.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...
- class字节码结构(二)(访问标志、类索引、父类索引、接口索引集合)
<Java虚拟机原理图解>1.3.class文件中的访问标志.类索引.父类索引.接口索引集合 字节码总体结构: 访问标志(access_flags)能够表示什么? 访问标志(access_ ...
随机推荐
- 转载hibernate 的3种 状态 。。
转自 http://huangtut.iteye.com/blog/261520 对我有帮助,所以收藏了 Hibernate三种状态的区分,以及save,update,saveOrUpdate,m ...
- KbmMW 4.5 发布
We are happy to announce the release of kbmMW v. 4.50.00 Professional, Enterprise and CodeGear Editi ...
- Web Service测试工具小汇
1..NET WebService Studio 这款工具出自微软内部,最大的优点是可视化很好,不用去看那些XML文件,WebService的基础内容就有XML,但是测试中Case过多,每次测试结果都 ...
- MySQL通过游标来实现通过查询记录集循环
/*我们有时候会遇到需要对 从A表查询的结果集S_S 的记录 进行遍历并做一些操作(如插入),且这些操作需要的数据或许部分来自S_S集合*//*临时存储过程,没办法,不能直接在查询窗口做这些事.*/d ...
- Android+PHP开发最佳实践
本书以一个完整的微博应用项目实例为主线,由浅入深地讲解了Android客户端开发和PHP服务端开发的思路和技巧.从前期的产品设计.架构设计,到客户端和服务器的编码实现,再到性能测试和系统优化,以及最后 ...
- [转] ubuntu安装Sublime Text 3并使用SublimeClang插件
原文地址:https://blog.csdn.net/cywosp/article/details/32721011 3. 安装强大的SublimeClang插件 SublimeClang是Subli ...
- [jquery-delegate] iphone_4s _iphone _5c_中不兼容jQuery delegate 事件(does not wok)
1. jQuery .on() and .delegate() doesn't work on iPad http://stackoverflow.com/questions/10165141/jqu ...
- 别具光芒Div CSS 读书笔记(一)
继承 边框(border).边界(margin).填充(padding).背景(background) 是不能继承的. table 中td不会继承body的属性,因此需要单独指定. 权重 ...
- Emmet常用语法
Emmet常用语法1.输入!和html:5(不能大写),按下TAB 键,快速生成一个 HTML5 的标准文档初始结构. html:xt 生成 HTML4 过渡型 html:4s 生成 HTML4 严格 ...
- [ACM_动态规划] hdu1003 Max Sum [最大连续子串和]
Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum ...