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

字段区:包括了字段计数器和字段数据区:

字段是指在类中定义的静态或者非静态的全局变量,而不是在类中的方法内定义的局部变量。

Field字段应该包含的信息:

field字段的访问标志(access_flags)占有两个字节16位,通过每一位来表示不同的特征

字段的数据类型表示:

field_info结构体中,存储的是指向了常量池中该字段的名称和字段描述符的索引。

属性表集合:

针对final修饰的字段会有一个ConstantValue属性,将字段的值关联起来,存放的是指向常量池的字段值的索引。

特别注意的是:

  1. ,为什么会存在多个ConstantValue(有点奇怪,要么就是上图画错了,应该是字段存在多个属性,而不是多个constantValue)。
  2. ,还有就是有个说法只有static的字段 才有这个属性,但是我测试,只有final修饰的才有这个属性。

我的测试:(只有final有constantValue属性)

  1. 代码的全局变量:
  2. int aa=;
  3. static int aaa=;
  4. final int b=;
  5. static final int c=;
  6.  
  7. 字节码字段区域如下:(javap -v xxx类名xxx打开 显示的效果,不是索引,可能和虚拟机版本也有关系吧)
  8. int aa;
  9. descriptor: I
  10. flags:
  11.  
  12. static int aaa;
  13. descriptor: I
  14. flags: ACC_STATIC
  15.  
  16. final int b;
  17. descriptor: I
  18. flags: ACC_FINAL
  19. ConstantValue: int
  20.  
  21. static final int c;
  22. descriptor: I
  23. flags: ACC_STATIC, ACC_FINAL
  24. ConstantValue: int

关于字段赋值的时机:

  1. public static final int MAX=;
  2. public int count=;
  1. a,对于非静态的field字段的赋值将会出现在实例构造方法<init>()中
  2. b,对于静态的field字段,有两个选择:
  3. 、在静态构造方法<cinit>()中进行;
  4. 、使用ConstantValue属性进行赋值

编译器对于静态field字段的初始化赋值策略:

  1. 如果finalstatic同时修饰一个字段,并且这个字段是基本类型或者String类型的,
    那么编译器在编译这个字段的时候,会在对应的field_info结构体中增加一个ConstantValue类型的结构体,在赋值的时候使用这个ConstantValue进行赋值;
  2. 如果该field字段并没有被final修饰,或者不是基本类型或者String类型,那么将在类构造方法中赋值。
  3.  
  4. 感觉有点问题:测试结果是有final就有ConstantValue属性。

一个例子:

  1. public class Simple {
  2. private transient static final String str ="This is a test";
  3. }

总结:对于字段区域是对接口和类的全局字段的描述,将字段各部分关联起来。

最后有一个疑问:对于不是final修饰的字段,常量池没有存放它的值,字段数据区域也没有存放。程序运行后怎么得到它的值的。

只能看接下,构造方法是否有存放了。

补充:对于全局变量的值是被编译在构造器中赋值的:

例子:Java字节码浅析(—)

  1. public class SimpleClass {
  2. public int simpleField = ;
  3. }

字节码中字段信息:

  1. public int simpleField;
  2. Signature: I
  3. flags: ACC_PUBLIC

字节的构造方法中赋值:

  1. public SimpleClass();
  2. Signature: ()V
  3. flags: ACC_PUBLIC
  4. Code:
  5. stack=, locals=, args_size=
  6. : aload_0
  7. : invokespecial # // Method java/lang/Object."<init>":()V
  8. : aload_0
  9. : bipush
  10. : putfield # // Field simpleField:I
  11. : return
  1. aload_0
  2. 从局部变量数组中加载一个对象引用到操作数栈的栈顶。尽管这段代码看起来没有构造方法,
  3.  
  4. 但是在编译器生成的默认的构造方法里,就会包含这段初始化的代码。第一个局部变量正好是this引用,
  5.  
  6. 于是aload_0this引用压到操作数栈中。aload_0aload_指令集中的一条,这组指令会将引用加载到操作数栈中。
  7.  
  8. n对应的是局部变量数组中的位置,并且也只能是0,,,。还有类似的加载指令,它们加载的并不是对象引用,
  9.  
  10. 比如iload_,lload_,fload_,和dload_, 这里i代表int,l代表long,f代表float,d代表double
  11.  
  12. 局部变量的在数组中的位置大于3的,得通过iload,lload,fload,dload,和aload进行加载,
  13.  
  14. 这些指令都接受一个操作数,它代表的是要加载的局部变量的在数组中的位置。
  15.  
  16. invokespecial
  17. 这条指令可以用来调用对象实例的构造方法,私有方法和父类中的方法。
  18.  
  19. 它是方法调用指令集中的一条,其它的还有invokedynamic, invokeinterface, invokespecial, invokestatic, invokevirtual.
  20.  
  21. 这里的invokespecial指令调用的是父类也就是java.lang.Object的构造方法。
  22.  
  23. bipush 它是用来把一个字节作为整型压到操作数栈中的,在这里100会被压到操作数栈里。
  24. putfield
  25. 它接受一个操作数,这个操作数引用的是运行时常量池里的一个字段,在这里这个字段是simpleField
  26.  
  27. 赋给这个字段的值,以及包含这个字段的对象引用,在执行这条指令的时候,都 会从操作数栈顶上pop出来。
  28.  
  29. 前面的aload_0指令已经把包含这个字段的对象压到操作数栈上了,而后面的bipush又把100压到栈里。
  30.  
  31. 最后putfield指令会将这两个值从栈顶弹出。执行完的结果就是这个对象的simpleField这个字段的值更新成了100

class字节码结构(三)(字段集合的结构)的更多相关文章

  1. JVM 字节码(三)异常在字节码中的处理(catch 和 throws)

    JVM 字节码(三)异常在字节码中的处理(catch 和 throws) 在 ClassFile 中到底是如何处理异常的呢? 一.代码块异常 catch catch 中的异常代码块在异常是如何处理的呢 ...

  2. Jpa/Hibernate 字节码增强:字段延迟加载

    JPA提供了@Basic注解,实现延迟加载字段的功能,如下: @Basic(fetch = FetchType.LAZY) @Column(name = "REMARK_CONTENT&qu ...

  3. 图解JVM字节码执行引擎之栈帧结构

    一.执行引擎      “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...

  4. java虚拟机5 字节码

    java字节码本质是java程序的格式化表示,便于机器处理.所以他是java程序的另一种表示,java程序包含的信息他都包含并且更加结构化. java虚拟机字节码格式: magic 魔数,标识该文件是 ...

  5. JVM 字节码执行实例分析

    前言 最近在看<Java 虚拟机规范>和<深入理解JVM虚拟机>,对于字节码的执行有了进一步的了解.字节码就像是汇编语言,是 JVM 的指令集.下面我们先对 JVM 执行引擎做 ...

  6. Java反射获取字节码以及判断类型

    一.获取类的字节码的三种方法: 1.使用Class.class   Class<?> c1=String.class; 2.使用实例.getClass()   String s= Clas ...

  7. class字节码结构(四)(方法集合的结构)

    <Java虚拟机原理图解>1.5. class文件中的方法表集合--method方法在class文件中是怎样组织的 一个类有多个方法,所以方法肯定是一个集合. 目标是: 1,了解方法在字节 ...

  8. java动态代理——字段和方法字节码的基础结构及Proxy源码分析三

    前文地址:https://www.cnblogs.com/tera/p/13280547.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...

  9. class字节码结构(二)(访问标志、类索引、父类索引、接口索引集合)

    <Java虚拟机原理图解>1.3.class文件中的访问标志.类索引.父类索引.接口索引集合 字节码总体结构: 访问标志(access_flags)能够表示什么? 访问标志(access_ ...

随机推荐

  1. 转载hibernate 的3种 状态 。。

    转自  http://huangtut.iteye.com/blog/261520  对我有帮助,所以收藏了 Hibernate三种状态的区分,以及save,update,saveOrUpdate,m ...

  2. KbmMW 4.5 发布

    We are happy to announce the release of kbmMW v. 4.50.00 Professional, Enterprise and CodeGear Editi ...

  3. Web Service测试工具小汇

    1..NET WebService Studio 这款工具出自微软内部,最大的优点是可视化很好,不用去看那些XML文件,WebService的基础内容就有XML,但是测试中Case过多,每次测试结果都 ...

  4. MySQL通过游标来实现通过查询记录集循环

    /*我们有时候会遇到需要对 从A表查询的结果集S_S 的记录 进行遍历并做一些操作(如插入),且这些操作需要的数据或许部分来自S_S集合*//*临时存储过程,没办法,不能直接在查询窗口做这些事.*/d ...

  5. Android+PHP开发最佳实践

    本书以一个完整的微博应用项目实例为主线,由浅入深地讲解了Android客户端开发和PHP服务端开发的思路和技巧.从前期的产品设计.架构设计,到客户端和服务器的编码实现,再到性能测试和系统优化,以及最后 ...

  6. [转] ubuntu安装Sublime Text 3并使用SublimeClang插件

    原文地址:https://blog.csdn.net/cywosp/article/details/32721011 3. 安装强大的SublimeClang插件 SublimeClang是Subli ...

  7. [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 ...

  8. 别具光芒Div CSS 读书笔记(一)

    继承 边框(border).边界(margin).填充(padding).背景(background) 是不能继承的.   table 中td不会继承body的属性,因此需要单独指定.   权重   ...

  9. Emmet常用语法

    Emmet常用语法1.输入!和html:5(不能大写),按下TAB 键,快速生成一个 HTML5 的标准文档初始结构. html:xt 生成 HTML4 过渡型 html:4s 生成 HTML4 严格 ...

  10. [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 ...