日期:2014-05-16  浏览次数:20594 次

[转]在Linux下编译OpenJdk并调试Hotspot
背景

对于大多数Java程序员来说,JVM就是一个黑盒子,我们一般不必关心它内部是怎么运作的。但是万一碰到JVM bug导致的Crash呢,又或者只是因为好奇想了解JVM的内部世界,那么就需要编译和调试JVM。
概念

1. JVM(Java Virtual Machine)

       翻译过来就是Java虚拟机,所谓虚拟机是相对传统的计算机而言的。

       传统的计算机有很多体系架构,比如x86,Sparc等等;一个体系架构一般有类似的指令集,比如586兼容所有386的指令集,但是又有自己扩充的指令。在Java出现之前,大部分编译型语言(我不知道是不是所有的)都会由编译器把源代码编译成特定机器下特定指令集的机器指令。从理论上来说所有的机器的表达能力都是一样的,等价于图灵机这个理论模型。但是就具体实现而言,在不同机器实现同一个逻辑的机器指令是不同的,这就导致在一台机器编译的二进制文件可能无法在另一台机器上运行(这里不考虑操作系统的差异)。当然写得比较好的c代码是可以在不同平台编译,但是一般不太可能把一个windows下的exe程序让linux运行。(当然除了机器指令的差别,不同系统的二进制格式也是不能兼容的,比如windows pe和linux elf)。即使同一个操作系统,比如linux,在x86下编译的程序也是没办法在Sparc下跑的,因为Sparc根本不认识x86的指令。

       JVM就是一个虚拟机,它定义了自己的指令集(Java字节码),所有的Java程序编译成统一的字节码,然后JVM负责在不同的硬件和操作系统下解释或者编译字节码。

       JVM本身只是一个概念,一种抽象

2. JRE(Java Runtime Environment)

       Java运行时环境,首先必须实现JVM规范,实现同样的JVM规范可以有很多方法,比如Sun有Sun的实现,IBM有IBM的实现。

       JVM当然得实现Java语言,也就是java.lang.*,认识int,知道class,方法,...

       但是如果你发现没有java.util.* 或者没有java.io.*时,是不是会发现没法写Java程序了呢?

       没有util,你当然可以自己实现那些常见的数据结构,这可以用java实现;那没有io呢?那似乎没法写出跨平台的代码了。

       所以除了实现语言本身,Java还定义了很多跨平台的API,比如java.awt java.io等等。这些可能是我们非常常用的,所以Sun把它们叫作了Java Standard Edition(Java SE)。一般以java开头

       另外有些API,比如JDBC,这是连接数据库的API。这些组成了Java Enterprise Edition(Java EE)。一般以javax包开头

       这些API有些是用Java实现,但很多不跨平台的必须由C实现(JVM通过JNI规范来实现Java和c的数据传递),所以JRE必须实现这些

3. JDK(Java Development Kit)

*       *开发者的工具,最常用的就是javac编译器。和vc或者gcc一样,必须要有工具把源代码编译成目标代码,c的目标代码是机器相关的,而Java的目标代码就是字节码。

*       *当然实现javac就是实现一个传统的编译器,词法分析,语法分析和语义分析,然后翻译成字节码。这本身不是件简单的事情,所以编译器的开发者也开发了一些帮助开发编译器的工具,比如我们熟悉的lex/flex,yacc/bison。java也实现了类似的JavaCC和JFlex。

       除了javac,javadoc和javah也是很常用的工具。此外Java的新特性,比如范型(Generics)和注解(Annotations),这些也需要由编译器来处理。(范型只影响编译,编译后被擦除了,但是Annotation可能会运行时能通过反射获取)。这些代码一般都是Java实现,打包到tools.jar。所以如果你需要动态编译Java代码(比如JSP),那么你可能要用到tools.jar
Linux下Build Open Jdk 7和Debug Hotspot

      下面的内容大部分参考下面两篇文章:

        http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop.html

        http://weblogs.java.net/blog/simonis/archive/2008/01/hotspot_develop_1.html

       不过在用NetBeans调试Hotspot时碰到了一些问题(可能是我用了比较新的netbeans的缘故),之前问过作者,不过没有得到满意的解答,后来自己使用了一些trick的手段。

1. 获取源代码

       两种方法

       1.1 使用 Mercurial 获取最新代码(其实就是svn git这样的scm工具)

             http://hg.openjdk.java.net/jdk7/build/raw-file/tip/README-builds.html

             速度比较慢,可能要花几个小时吧,如果你需要最新代码又不想等,可以找我

       1.2 直接下载压缩的源代码包

             http://download.java.net/openjdk/jdk7/

             解压后就可以了,如果想更新代码,也可以运行 sh ./getSource.sh更新

        1.3 源代码结构

             hotspot

                  hotspot的源代码,完整的工程,包括makefile,文件按平台分类,比如 hotspot/src下有4个目录: