深入理解Java虚拟机04--类结构文件

时间:2018-08-06 11:25:46   收藏:0   阅读:134

一.程序存储格式

二.Class 文件结构

Class 文件是以 8 个字节为单位的二进制流,紧凑排列,中间没有空隙;如果想查看一个 Class 文件除了通过 winHex 编译器看到字节码,也可以通过 javap -verbose xxx.Class 输出字节码内容,这样看起来比较直观。
1、基本类型
无符号数:

表:

2、魔数与版本

3、常量池
  版本号之后紧跟的就是常量池入口,可以理解为Class文件之中的资源仓库;

  1. 0项常量:不引用任何一个常量池项目
  1. 字面量:文本字符串、final常量值等;
  2. 符号引用
    • 类和接口的全限定名
    • 字段的名称和描述符
    • 方法的名称和描述符
  1. 定义:UTF-8编码的字符串长度是多少个字节;
  2. 65535限制:Class文件中方法、字段等都需要引用CONSTANT_ Utf8_ info型常量的length为u2类型,最大为65535.如果某个变量或者方法名超过了64K,那么这个length容不下了,当然也就无法编译了。

4、访问标志(access_flags)

5、类索引、父类索引和接口类集合

6、字段表集合(field_info)

    1. 作用域:public、private、protect
    2. 实例or类变量:static
    3. 可变性:final
    4. 并发可见性:volatile
    5. 是否可序列化:transient
    6. 字段数据类型:基本类型、对象、数组等
    7. 字段名称;
    1. 1、不会列出超类or父类或者父接口继承而来的字段;
    2. 2、有可能列出原本Java代码中不存在的字段(内部类会自动添加指向外部类实例的字段,才能引用到外部类);
    3. 3、Java语言中字段是无法重载的;

7、方法表集合
和字段表集合差不多,方法表集合用来描述Class文件中的方法,但是访问标志和属性表集合和字段表集合有所区别;

8、属性表集合(attribute_info)
上述那些表需要携带自己的某些属性,来描述自己的特殊环境信息,比如InnderClasses、LineNumberTable、Code 之类的;

 

三.字节码指令
1、字节码组成

Java虚拟机采用面向操作数栈而不是寄存器的架构,字节码指令集是一种指令集架构。放弃了操作数对齐,省略了填充的符号和间隔。
2、加载和存储指令
将数据在帧栈中将局部变量表和操作数栈之间来回传输。

3、运算指令

4、类型转换指令

5、同步指令

 三.代码举例

1、Java文件:

 1 package com.xxx.ccc;
 2 public final class InitConfig {
 3     public static final InitConfig BFCACCOUNT = new InitConfig(0, "aaa", "AAA");
 4     private int mIndex;
 5     private String mData;
 6     private String mDescribe;
 7     private InitConfig(int indexFlag, String data, String describe) {
 8         this.mIndex = indexFlag;
 9         this.mData = data;
10         this.mDescribe = describe;
11     }
12     public String getmData() {
13         return this.mData;
14     }

2、Class 文件:

 1 Last modified 2017-7-4; size 1050 bytes
 2 MD5 checksum 2beb0c10f91b793c3570edcf2d1eff78
 3 Compiled from "InitConfig.java"
 4 public final class com.xxx.xxx.InitConfig
 5 minor version: 0  //次版本号
 6 major version: 51 //主版本号
 7 flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER  //访问标志
 8 Constant pool: //常量池
 9  #1 = Methodref          #14.#41        // java/lang/Object."<init>":()V
10  #2 = Fieldref           #5.#42         // com/xxx/xxx/InitConfig.mIndex:I
11  #6 = Class              #46            // com/xxx/xxx/common/constant/ConstData
12  #7 = String             #47            // aaa
13  #23 = Utf8               <init>
14  #24 = Utf8               (ILjava/lang/String;Ljava/lang/String;)V
15  #25 = Utf8               Code
16  #26 = Utf8               LineNumberTable  //Java的源码行号和字节码行号
17  #27 = Utf8               LocalVariableTable //局部变量表中的变量与Java源码中定义的变量之间的关系
18  #28 = Utf8               this
19  #32 = Utf8               getmData
20  #33 = Utf8               ()Ljava/lang/String;
21  #37 = Utf8               <clinit>
22  #38 = Utf8               ()V
23  #40 = Utf8               InitConfig.java
24  #41 = NameAndType        #23:#38        // "<init>":()V
25  #45 = Utf8               com/xxx/xxx/InitConfig
26  #46 = Utf8               com/xxx/xxx/common/constant/ConstData
27  #53 = NameAndType        #17:#16        // SEAACCOUNT:Lcom/xxx/ccc/InitConfig;
28  #54 = Utf8               java/lang/Object
29 public static final com.xxx.xxx BFCACCOUNT;
30     descriptor: Lcom/xxx/xxx/InitConfig;
31     flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL 
32 public java.lang.String getmData();
33     descriptor: ()Ljava/lang/String;
34     flags: ACC_PUBLIC
35     Code:
36          stack=1, locals=1, args_size=1
37             0: aload_0
38             1: getfield      #3                  // Field mData:Ljava/lang/String;
39          4: areturn
40           LineNumberTable: //Java的源码行号和字节码行号
41             line 36: 0
42           LocalVariableTable: //局部变量表中的变量与Java源码中定义的变量之间的关系
43             Start  Length  Slot  Name   Signature
44                0       5     0   this   Lcom/xxx/xxx/InitConfig;  //方法里面默认增加了个this

四.小结

  为什么说一些”非Java"语言也是可以在 JVM 上跑,这是因为 JVM 只认识 Class 文件,所以如果某某语言最终编译出的文件是 Class 文件,那么对于 JVM 来说没有什么区别,但是得按照 Class 文件的结构来,不然也无法正常执行。Class 定义了许多特定的基本类型和表结构,通过魔数让 JVM 认识该文件,版本号保证可以在要求的 JDK 版本上运行,在常量池中定义好常量,访问标志位确定访问权限。索引集合方便与外界的 class 保持联系,字段表保存我们定义好的变量,方法表存储方法的信息,属性表存储了上述各种表的一些属性。其中记住 slot为局部变量分配内存的最小单位,当程序超出作用域的时候,slot 可以被其他替换使用。到这里,仅仅是代码最静态的存储的格式,程序要运行起来。还需要操作指令,也是由字节码存储,包括操作码和操作数。有加载存储、运算、类型转换、同步指令。

原文:https://www.cnblogs.com/ganchuanpu/p/9429248.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!