关闭

【理解HostSpot虚拟机】class文件格式

标签: 虚拟机java
443人阅读 评论(0) 收藏 举报
分类:

转载请注明出处:http://blog.csdn.net/linxdcn/article/details/73472553


1 概述

Java编译后的class文件格式如下定义:

ClassFile {
    u4             magic;
    u2             minor_version;
    u2             major_version;
    u2             constant_pool_count;
    cp_info        constant_pool[constant_pool_count-1];
    u2             access_flags;
    u2             this_class;
    u2             super_class;
    u2             interfaces_count;
    u2             interfaces[interfaces_count];
    u2             fields_count;
    field_info     fields[fields_count];
    u2             methods_count;
    method_info    methods[methods_count];
    u2             attributes_count;
    attribute_info attributes[attributes_count];
}
  • magic:魔数,固定为0xCAFEBABE
  • minor_version:次版本号
  • major_version:主版本号
  • constant_pool_count:常量池项个数
  • constant_pool[constant_pool_count-1]:常量池表,长度为constant_pool_count-1
  • access_flags:类或接口的访问标志
  • this_class:当前类
  • super_class:超类
  • interfaces_count:接口数量
  • interfaces[interfaces_count]:接口表
  • fields_count:字段数量
  • fields[fields_count]:字段表
  • methods_count:方法数量
  • methods[methods_count]:方法表
  • attributes_count:属性数量
  • attributes[attributes_count]:属性表

关于class文件中的各项说明,可以参考虚拟机规范或者底下参考文献的两篇文章,已经总结的非常的详细,本文对其中重要的几项作一个总结。


2 常量池

  • 常量池保存了文件中类或接口相关的一切常量:
    • 字面量:文字字符串、final变量值、基础数据类型
    • 符号引用:如类或接口的全限定名、方法或字段的简单名称和描述符

根据虚拟机规范,常量池项目类型有以下分类



JVM规范规定的常量池项目类型

规范规定的总是很抽象的,下面举几个例子就好懂。

2.1 int a = 10

类型 常量池索引 备注
CONSTANT_Integer 1 10 字面量:基础数据类型

2.2 String a = “test”

类型 常量池索引 备注
CONSTANT_String 1 #2 符号引用
CONSTANT_Utf8 2 test 字面量:文字字符串

2.3 Date a = new Date()

类型 常量池索引 备注
CONSTANT_Class 1 #1 符号引用:类全限定名
CONSTANT_Utf8 2 Ljava/util/Date; 字面量:文字字符串

2.4 Field常量

在类中定义了field 字段,并且在类的其他地方(如方法中)使用到它,这是会用到Field常量,如以下代码

Class Test {
    String name;
    public void setName(String a) {
        // 这里会使用Field常量
        name = a;  // 翻译成指令为: getfield    #5
    }
}
类型 常量池索引 备注
CONSTANT_Class 1 #2 符号引用
CONSTANT_Utf8 2 package/path/Test 字面量:文字字符串
CONSTANT_Utf8 3 name 字面量:文字字符串
CONSTANT_Utf8 4 Ljava/lang/String; 字面量:文字字符串
CONSTANT_Fieldref 5 #1.#6 符号引用
CONSTANT_NameAndType 6 #3.#4 符号引用

2.5 Method常量

假如我们只定义了方法,但是这些方法没有在类总的其他地方被用到(如2.3中的代码),则这些方法引用信息并不会放到常量中。下面代码则可以使用到Method常量。

Class Test {
    String name;
    public String getName() {
        return name;
    }
    public do() {
        // 这里会使用Method常量
        setName("test");  // 翻译成指令为: invokevirtual    #5
    }
}
类型 常量池索引 备注
CONSTANT_Class 1 #2 符号引用
CONSTANT_Utf8 2 package/path/Test 字面量:文字字符串
CONSTANT_Utf8 3 getName 字面量:文字字符串
CONSTANT_Utf8 4 ()java/lang/String; 字面量:文字字符串
CONSTANT_Methodref 5 #1.#6 符号引用
CONSTANT_NameAndType 6 #3.#4 符号引用

3 字段表-field_info[]

首先需要说明的是,属性不仅在class文件结构中使用,在field_info和method_info中也使用。

在字段域出现的属性有ConstantValue(final常量)、Deprecated(被禁用的指示符)、Synthetic(编译器产生的指示符)。

4 方法表-method_info[]

方法域出现的属性有Code、Deprecated、Exceptions、Synthetic 。

(1)Code

Code类型的属性表(attribute_info)可以说是class文件中最为重要的部分,因为它包含的是JVM可以运行的机器码指令,JVM能够运行这个类,就是从这个属性中取出机器码的。

Code属性表包含:

  • 机器指令—-code:
  • 异常处理跳转信息—exception_table
  • Java源码行号和机器指令的对应关系—LineNumberTable属性表
  • 局部变量表描述信息—-LocalVariableTable属性表

5 一些思考

(1)常量池的CONSTANT_Fieldref和跟字段域field_info的区别?

CONSTANT_Fieldref,这只是一个字段的符号引用,通常作为字节码指令(opcode)getfield/getstatic/putfield/putstatic的操作数使用。

field_info是类中定义字段本身信息的描述,关于类加载过程中field部分的解析,以及其作为InstanceKlass类中成员属性的layout。

对于getfield/getstatic/putfield/putstatic四种与Field Reference相关的指令,在字段决议——resolve_field时,会有两者的协同使用——根据符号引用去_field中查找真正的字段。符号引用只是一个对应字段的一个字符串,符号引用经第一次解析(解析结果存入ConstantPoolCache),就会变成直接引用——field_offset。

对于CONSTANT_Methodref和方法域method_info也类似。

(2)如何防止class文件被劫持?

主要通过类加载双亲委派模型实现。

jvm首先会检查该类是否已经被加载,若没有被加载,则会委托父加载器进行装载,只有当父加载器无法加载时,才会调用自身的findClass()方法进行加载。这样避免了子加载器加载一些试图冒名顶替可信任类的不可靠类,也不会让子加载器去实现父加载器实现的加载工作。

并且jvm规定只有运行时包(同一个类加载器加载的、属于同一个包的多个类型集合),才能访问同一包内的类(和其子类)的protected成员。

(3)如何防止class文件反编译?

可以参考下这篇博客:http://blog.csdn.net/yuxiaohui78/article/details/8247096


6 参考

http://blog.csdn.net/luanlouis/article/details/39892027
http://www.cnblogs.com/iceAeterNa/p/4874197.html


转载请注明出处:http://blog.csdn.net/linxdcn/article/details/73472553

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:24174次
    • 积分:734
    • 等级:
    • 排名:千里之外
    • 原创:51篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    博客专栏