设为首页 加入收藏

TOP

实例探索Class文件(一)
2017-09-30 16:34:55 】 浏览:3016
Tags:实例 探索 Class 文件

class文件是指以.class为 文件后缀的Java虚拟机可装载文件。无论该class文件是在linux上进行编译的,还是在windows环境下编译的,无论虚拟机是在何种平台下实 现和运行的,class文件使得Java虚拟机可以正确的读取、解释所有的class文件。 在分析和研究class文件之前,先提出有一些问题:

1.类/接口(class文件也可能定义的是接口,所以还是不要理解为类文件为好)内有哪些内容?

2.以上内容分别保存在class文件的什么地方?

3.这些内容在加载过程中又如何被读取和解析?

4.这些内容加载后又会被解析成为什么样的数据结构保存在虚拟机中?

5.这些数据结构在虚拟机的运行过程中又是如何被使用的?

扩展问题:

6.如何防止class文件被劫持?

7.如何防止class文件被反编译?

 

class文件的组织结构定义如下:

ClassFile{
magic                        u4,
minor_version                u2,
major_version                u2,
constant_pool_count            u2,
constant_pool                cp_info*constant_pool_count,
access_flags                 u2,
this_class                   u2,
super_class                  u2,
interface_count              u2,
interfaces                   u2 * interface_count,
fields_count                 u2,
fields                      field_info * fields_count,
methods_count                u2,
methods                      method_info * methods_count,
attributes_count             u2,
attributes                   attributes_info * attributes_count
}

以如下程序为例,对生成的class文件进行分析:

//TestInterface.java
public interface TestInterface {
    public void interface_method();
}

//TestClass.java
public class TestClass implements TestInterface{
    private int private_global = 3;
    public int public_global;
    private static final int sfi = 127;
    public static final String sfs = "test strings";
    private StringBuilder sb;
    
    public void method_1(){
        private_global = public_global * 2;
        sb.append(private_global);
    }
    
    public void method_2(int pub){
        public_global = pub;
    }

    public void method_2(int pub, boolean flag){
        int tmp = 5;
        public_global = pub * 2 + tmp;
    }
    
    @Override
    public void interface_method() {
        method_1();
    }
    
}

1.magic(魔数) 值为0xcafebabe,没有特别的意义,放在文件头并选取用来标记改文件是一个class文件。

 

2.minor_version/major_version(次版本号和主版本号)

次版本号和主版本号分别为0×0000和0×0032(50),即主版本号位50,次版本号为0

 

3.constant_pool_count/constant_pool(常量池数量和常量池)

常量池保存了文件中类或接口相关的一切常量,字面常量(直接量),如文字字符串、final变量值,以及符号引用,如类或接口的全限定名、方法或字段的简单名称和描述符

其中,全限定名用以在当前命名空间内唯一标志类或接口,在java语言中如java.lang.Object,在class文件中,会将’.'用’/'取代,即表示为java/lang/Object 简单名称就是简单的方法名或变量名的字符串,如java.lang.Object的成员方法wait()的简单名称为”wait”。

而只有简单名称是无法唯一确定调用的方法是哪一个,由于Java语言的特性,方法可能被重写或重载, 所以还需要根据方法的返回值、参数数量、类型、顺序来确定一个方法描述符来唯一标志该方法,字段的描述符则简单得多,只需要给出字段的类型 描述符让我们联想起PE/ELF文件的函数签名,它由上下文无关语法定义:

FieldDescriptor:
            FieldType
ComponentType:
            FieldType
FieldType:
            BaseType
            ObjectType
            ArrayType
BaseType:
            B
            C
            D
            F
            I
            J
            S
            Z
ObjectType:
            L<classname>;
ArrayType:
            [ComponentType
MethodDescriptor:
            (ParameterDescriptor*) ReturnDescriptor
ParameterDescriptor:
            FieldType
ReturnDescriptor:
            FieldType
            V

其终结符号如下:

以深入java虚拟机上的示例作为参考:

    &nb

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇深入探索 Java 热部署 下一篇实例分析JVM安全体系:双亲委派、..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目