Java编译原理

来源:互联网 发布:傻瓜自动写作软件 编辑:程序博客网 时间:2024/04/30 15:53

代码Test.java

public class Test {        public static void main(String[] args) {            int a = 0xae;            int b = 0x10;            int c = a + b;            int d = c + 1;            String s;            s = "hello";        }    }

# javac  Test.java

# javap -c Test

参考:http://codemacro.com/2015/03/31/intro-java-bytecode/ 

*.class文件就已经是编译好的byte code文件,就像C/C++编译出来的目标文件一样,已经是各种二进制指令了。这个时候可以通过JDK中带的javap工具来反汇编,以查看对应的byte code。

JVM中每个指令只占一个字节,操作数是变长的,所以其一条完整的指令(操作码+操作数)也是变长的。上面每条指令前都有一个偏移,实际是按字节来偏移的。

从上面的byte code中,以x86汇编的角度来看会发现一些不同的东西:

局部变量竟是以索引来区分:istore_1 写第一个局部变量,istore_2写第二个局部变量,第4个局部变量则需要用操作数来指定了:istore 4
函数调用invokespecial #1竟然也是类似的索引,这里调用的是Object基类构造函数
常量字符串也是类似的索引:ldc #2

整个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];     //属性表
}
这明显已经不是以区段来分的格式了,上面提到的函数索引、常量字符串索引,都是保存在constant_pool常量池中。常量池中存储了很多信息,包括:

各种字面常量,例如字符串
类、数据成员、接口引用
常量池的索引从1开始。

Java Class文件详解 【写的极好】

常量池的索引从1开始。对于上面例子Test.java,可以使用

javap -v Test

查看其中的常量池



代码Foo.java

<pre name="code" class="java">public class Foo{private static final int MAX_COUNT=1000;private static  int count=0;public int bar() throws Exception{if(++count >= MAX_COUNT){count=0;throw new Exception("count overflow");}return count;}


# javac -g Foo.java

# javap -c -s -l -verbose Foo


0 0
原创粉丝点击