`
wpf_00
  • 浏览: 43334 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类

(openJDK)Javac1.7编译器源码分析_001_简介与安装

阅读更多

网站:JavaEye 作者:zhh2007 发表时间: 2007-05-30 23:51 此文章来自于 http://www.iteye.com
声明:本文系JavaEye网站原创文章,未经JavaEye网站或者作者本人书面许可,任何其他网站严禁擅自发表本文,否则必将追究法律责任!
原文链接: http://www.iteye.com/topic/84833

(openJDK)Javac1.7编译器源码分析_001_简介与安装

(第一次写Blog,此文只是本人的一点点学习记录,不经本人事先同意请勿随意转载,谢谢)


1.1:简介:


1.1.1 javac版本


SUN公司在2006年11月份已将java语言编译器(javac)源码通过GPLv2的方式开源,

还建立了“the Open-Source JDK Community”,网址是:http://openjdk.java.net/





截止到写这篇文章时,最新的javac Source Release已到了b13,

一般是半个月出一个beta版,从b04到b13变化都不大,javac类文件没有添加一个。

本文以及后续文章都是基于以下版本:

compiler-7-ea-src-b10-21_mar_2007 (为了方便起见,以后都简写成javac1.7)




1.1.2 我最初想到要分析javac源码的原因


a 看编译原理的书理论太多,想找个实际的编译器验证一下理论

b 之前在JDK1.4下写过一些java程序

c 对javac感兴趣,想要了解所有细节

d 要是还想分析HotSpot VM,先看javac有利

e 偶尔想到要反编译别人的代码




1.1.3 分析javac源码前最好具备的条件


a 编译原理的知识基本上忘记了不要紧,

  但还记得有LL(1)文法、递归下降算法、运算符优先这几个名词


b 知道基本的java语言语法,

  要是像我一样起初不懂Java 5之后的语言新特性也不要紧


c 越有耐心越好




1.1.4 java语言编译器是用什么语言编写的?


javac1.7的源代码本身是用java语言写的(用编译原理的术语叫“自举”),

源代码总行数不到8万行。


在James Gosling的blog上有一篇文章:

“Compiler fun” (http://blogs.sun.com/jag/entry/compiler_fun)

里面有提到最初的java语言编译器是用C语言写成的,不过我不能准确的知道从哪个

JDK发行版开始正式用java语言重写编译器,我尝试在JDK1.4到JDK1.6的tools.jar文件中

寻找javac,只能确定在JDK1.4到JDK1.6内嵌的java语言编译器都是java语言写的。


JDK1.6中的javac与开源的javac1.7生成的字节码几乎没有差别,这也肯定了一点:

开源的javac1.7并不是SUN公司为开源社区单独开发的一个版本,

javac1.7最终也会纳入未来的JDK1.7一起发行。


在“the Open-Source JDK Community”的邮件列表上也有一封邮件证实了这一点:

主题:OpenJDk7 opensource compiler final Java 7 compiler?

URL :https://openjdk.dev.java.net/servlets/ReadMsg?list=compiler-dev&msgNo=270




1.1.5 javac1.7编译流程概述


javac1.7的编译流程可以简单分为以下主要阶段:

(只大概说了一下,还有无数的细节问题会在以后详述,

有看到很讨厌的名词可以直接跳过这一节)


1) javac命令行选项及选项参数处理


   这一阶段主要是识别javac命令行选项是否是合法的,选项参数是否正确




2) 词法分析


   从头到尾分析源文件的字符流,形成关键字、标识符、数字、运算符等等

   具有独立意义的token序列,并去掉源文件中的空白与注释。




3) 语法分析


   词法分析在javac1.7中其实是做为语法分析阶段的一个过程(或方法)来

   驱动的,整个语法分析阶段完成的任务就是按照java语言的LL(1)文法

   采用递归下降算法并结合运算符优先规则,对token序列构造一棵

   抽象语法树(abstract syntax tree)




4) 符号识别(符号表)


   一个包、一个类、一个方法、一个字段都可以抽象成一个符号(symbol),

   不同种类的符号之间可以有包含嵌套关系:

   一个包符号可以包含多个类符号,

   一个类符号可以包含多个方法符号与多个字段符号。


   这一阶段的任务就是识别出各类符号,并对不同种类的符号按

   照包含嵌套关系进行归类,并挂接到抽象语法树对应的结点域。




5) 注释处理(可选阶段)




6) 属性分析(或称语义分析)

   这一阶段包含了一个复杂的类型系统,语义分析阶段检查语言规范中

   定义的各类规则




7) 数据流分析


   这一阶段主要是检查final类型的字段与方法中定义的局部变量是否被赋值




8) Desugar


   在Java 5之后增加了很多语言新特性,但是JVM规范却没有什么变动,

   JVM指令集也没有增加,所以在这一阶段的任务主要是把采用新语言

   特性写成的源代码自动翻译转换成未使用新特性写成的代码。

   如:泛型类到普通类的转换,enhanced for loop到普通for loop的转换。

 


9) 代码生成


   构造常量池、筛选指令、生成class文件。




9) 错误处理:


   错误处理贯穿编译流程的所有阶段




其他:

javac1.7中没有使用像Lex、YACC这样的生成器工具,

词法、语法分析与代码生成全都是手工实现的,具有简单、灵活、高效的

特点,传统编译原理课本上讲授的知识更具通用性,但过于复杂,效率也是

个问题。

另外,可惜的是javac1.7(包括sun公司以往发行的JDK中内置的javac)不是

一个优化编译器,javac1.7并没有独立的优化阶段,

散落在其他阶段的“优化”可以省略不计。


比如:(例子不考虑人的因素,只考虑编译器的行为):


java 代码




  1. package my.test;   

  2. public class Test {   

  3.     Test() {   

  4.         int v1=1;   

  5.         while(v1<10000) {   

  6.             int v2=5;   

  7.             v1=v1+v2*2;   

  8.         }   

  9.     }   

  10. }  



用javac1.7或JDK1.6.0生成的字节码如下(部分内容)

(用命令行“javap -verbose my.test.Test”查看):

---------------------------------------------------

my.test.Test();

  Code:

   Stack=3, Locals=3, Args_size=1

   0: aload_0

   1: invokespecial #1; //Method java/lang/Object."":()V

   4: iconst_1  //将常量1压入堆栈

   5: istore_1  //将常量1弹出堆栈并存入局部变量v1,

   6: iload_1   //将局部变量v1的值压入堆栈

   7: sipush 10000   //将常量10000压入堆栈

   10: if_icmpge 24  //弹出常量10000,弹出局部变量v1的值,局部变量v1的值>=10000结束循环

   13: iconst_5  //将常量5压入堆栈

   14: istore_2  //将常量5弹出堆栈并存入局部变量v2,

   15: iload_1   //将局部变量v1的值压入堆栈

   16: iload_2   //将局部变量v2的值压入堆栈

   17: iconst_2  //将常量2压入堆栈

   18: imul      //弹出常量2,弹出局部变量v2的值,相乘后将结果压入堆栈

   19: iadd      //弹出结果,弹出局部变量v1的值,相加后将结果压入堆栈

   20: istore_1  //弹出结果并存入局部变量v1

   21: goto 6 //转到6: iload_1

   24: return

---------------------------------------------------


理想的优化编译器应该能生成如下类似的代码:


java 代码




  1. package my.test;   

  2. public class Test {   

  3.     Test() {   

  4.         int v1=1;   

  5.         while(v1<10000) {   

  6.             v1=v1+10;//v2=5与v2*2总是不变的,可以合并成10   

  7.         }   

  8.     }   

  9. }  





更理想的优化编译器应该能生成如下类似的代码:


java 代码




  1. package my.test;   

  2. public class Test {   

  3.     Test() {}//局部变量v1没有任何用处,完全可以删除   

  4. }  



关于编译流程简短说明的文档也可参考

Peter von der Ahé(javac编译器的主要开发者,前段时间已离开SUN公司)

在“the Open-Source JDK Community”的邮件列表上回复的一封邮件

主题:A set ot tutorials about the compiler

URL :https://openjdk.dev.java.net/servlets/ReadMsg?list=compiler-dev&msgNo=89




1.1.6 在没有任何设计文档的前提下如何分析javac1.7源码?


我只说说我采用的方法(我是第一次分析别人的源代码):

1) 找到一种最简单的办法完成源代码的第一次编译

2) 找到第一个开始运行的类文件(也就是找到切入点)

3) 粗略看一下这个类文件定义了哪些字段,有构造方法的话,

   粗略看一下构造方法中做了哪些初始化工作

4) 要是定义的字段、构造方法太多,把它们都copy一份,单独放到一个文件


5) 找到第一个被运行的方法,

   在方法开头和末尾打上Debug(包装System.out.println()后写成的一个类),

   觉得关键的字段(或局部变量),用自己喜欢的方式也打上Debug,

   如果类文件源码超过200行(javac1.7源码中有许多核心类文件大多超过1000行),

   为了切换方便,把这方法copy一份,单独放到一个文件


6) 当在一个方法中调用了另一个类的方法时,转到3)

7) 当一个类文件中定义的方法有85%都已Debug过了,从头到尾细细分析一遍类文件

8) Debug的输出信息最好重定向到一个自定义的文件

9) 方法中有复杂算法时最好用笔画在纸上


10)有很多个方法同时来回调用时,把每个方法按调用的顺序单独打开,对照Debug

   信息一起看(我经常打开5、6个EditPlus窗口实例同时看20几个类文件)


11)记住随心所欲地想把一个个类文件不打Debug、不按流程顺序分析,是非常低效

   的一种方法,除非这个类文件很独立,只是简单的字段值存取功能。


 


1.2:安装


1.2.1 运行环境


我的OS是Windows XP


建议安装JDK1.6,我的JDK版本是

-------------------------------

java version "1.6.0-beta2"

Java(TM) SE Runtime Environment (build 1.6.0-beta2-b86)

Java HotSpot(TM) Client VM (build 1.6.0-beta2-b86, mixed mode, sharing)

-------------------------------


安装JDK后,请在系统变量Path中加入 %JAVA_HOME%\bin,

其中%JAVA_HOME%是JDK安装目录。




1.2.2 下载javac1.7源码


下载地址:

http://www.java.net/download/openjdk/jdk7/promoted/b10/compiler-7-ea-src-b10-21_mar_2007.zip

解压后会有一个“compiler”目录,

如果你习惯使用Ant、NetBeans或其他IDE工具编译源码,请直

接参考“compiler\README.html”文件,然后跳到“第1.3节”;

如果你像我一样不会用(或不想用)IDE或想操控一切,

请按下面的简单步骤操作:




1.2.3 下载附件中的"Javac.jar"文件,解压到一个目录(这里以“F:\Javac”为例)

(注:"Javac.jar"文件只包含了“compiler\src\share\classes”目录下的

两个子目录“com”与“javax”,其他子目录或文件都是我自建的,javac1.7源码中

还包含了无数的测试用例,我觉得它太繁琐了,就自己一边看源码,一边写自己的

测试例子,所以我把它省略掉了)




1.2.4 编译javac1.7源码


打开一个Dos命令行窗口,切换到“F:\Javac”目录

输入“com”按回车,稍等片刻就可以完成编译




1.2.5 用javac1.7编译其他java源文件


打开一个Dos命令行窗口,切换到“F:\Javac”目录

输入“run”按回车,打开“F:\Javac\myout.txt”文件,就可以看到Debug信息。

在F:\Javac\run.bat文件中默认是编译F:\Javac\bin\mysrc\my\test\Test.java文件

你可以随意替换成你自己的java源文件


1.2.6 javac1.7源码的切入点是F:\Javac\com\sun\tools\javac\Main.java文件


 


1.3:几个有帮助的网址


James Gosling 的blog:

http://blogs.sun.com/jag/


Peter von der Ahé 的blog:

http://blogs.sun.com/ahe/


the Open-Source JDK Community:

http://openjdk.java.net/


The Java Language Specification, Third Edition:

http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html


The JavaTM Virtual Machine Specification Second Edition

http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html




<<深入Java虚拟机(原书第2版)>>

作者:Bill Venners

译者:曹晓钢,蒋靖 


书译得还可以,不过还是有很多印刷错误,

第6章和附录对理解代码生成有一定价值。


中文版地址:

http://www.china-pub.com/computers/common/info.asp?id=14719


Bill Venners维护的网站:

http://www.artima.com/insidejvm/resources/




JDK6的文档(特别是语言新特性部分)也有参考价值





《 (openJDK)Javac1.7编译器源码分析_001_简介与安装 》 的评论也很精彩,欢迎您也添加评论。查看详细 >>

推荐相关文章:
  正确认识memcached的缓存失效
  ThreadLocalizer




JavaEye推荐
上海乐福狗信息技术有限公司:诚聘技术经理和开发工程师
免费下载IBM社区版软件--它基于开放的标准,支持广泛的开发类型,让您的开发高效自主!
京沪穗蓉四地免费注册,SOA技术高手汇聚交锋.
上海:优秀公司德比:高薪诚聘 资深Java工程师
广州:优易公司:诚聘Java工程师,开发经理
上海:尤恩斯国际集团:诚聘开发工程师
北京:优秀公司NHNChina招聘:WEB开发,系统管理,JAVA开发, DBA


分享到:
评论

相关推荐

    javac1.7源代码(完全版,可运行)

    本资源提供的"javac1.7源代码"是一个完全版,包含了OpenJDK 1.7版本中的javac编译器的源代码。OpenJDK是一个开源实现的Java平台标准版(Java SE),它提供了Java虚拟机(JVM)、类库以及Java语言编译器等关键组件。 ...

    openjdk 1.7 windows 64位

    5. 验证:通过在命令行输入`java -version`和`javac -version`,检查Java和Java编译器的版本,确认安装成功。 OpenJDK 1.7.0 u80的关键特性包括: 1. 字符串in-place替换优化:提升了字符串替换操作的效率。 2. ...

    openjdk1.7 附属源码src.zip

    《深入剖析OpenJDK 1.7源码》 OpenJDK 1.7源码是Java开发领域的重要参考资料,它揭示了Java平台的核心运行机制,对于开发者来说,理解和研究OpenJDK源码有助于提升编程技能,优化代码性能,以及解决实际问题。src....

    opentjdk1.7源码(jdk_ri-7u75-b13-windows-i586-18_dec_2014.zip)

    《OpenJDK 1.7源码解析:深入理解Java虚拟机与运行机制》 OpenJDK 1.7源码是Java开发人员探索Java虚拟机(JVM)内部工作原理的重要参考资料,它包含了Java开发工具集(JDK)的核心组件和实现。OpenJDK是一个开源...

    openJDK1.7/Java Development Kit7

    JDK包含了开发和运行Java应用程序所需的所有工具,包括Java编译器(javac)、Java虚拟机(JVM)、Java运行时环境(JRE)以及各种实用工具和API。对于开发者而言,它是一个基础性的开发工具包。 OpenJDK 1.7版本引入...

    openjdk-1.7.0-u80-windows-amd64-new.zip

    OpenJDK是Java Development Kit(JDK)的一个分支,它包含了Java运行环境(JRE)、Java编译器(javac)和其他必要的开发工具。 在"openjdk-1.7.0-u80-windows-amd64-new.zip"这个压缩包中,我们主要会找到以下几个...

    openjdk 1.7 windows 32位

    2. `bin` 目录:存放着各种命令行工具,如`javac`(Java编译器)、`java`(JVM执行器)和`jar`(打包工具)等。 3. `lib` 目录:包含了Java库文件,如类库和API文档。 4. `docs` 或 `doc` 目录:可能包含OpenJDK ...

    openJDK-7.tar.gz

    JDK提供了javac编译器,用于将Java源代码转换为字节码,以及各种工具,如Javadoc(生成API文档)、jar(打包类文件)和junit(单元测试)等。 **安装和使用openJDK-7** 在Linux环境下,解压openJDK-7.tar.gz通常会...

    OpenJdk-7.zip

    OpenJDK-7与Oracle JDK在功能上基本一致,但OpenJDK是开放源代码的,对于那些希望查看源码或者对Java技术进行研究的开发者来说,OpenJDK具有一定的优势。然而,由于OpenJDK可能没有Oracle JDK那样频繁的更新,所以在...

    Ubuntu16.04、Ubuntu18.04、或更高Ubuntu版本安装JDK7参考资料

    Oracle JDK 7的支持已经结束,但OpenJDK 7作为一个开源替代品仍然可以获取和安装。以下是一个详细的安装指南: 首先,我们需要更新系统软件包列表,确保我们能够获取到最新的依赖项和更新。打开终端并输入以下命令...

    openjdk1.7.0_151-amd64.zip

    "aosp" 是 Android 开放源码项目(Android Open Source Project)的缩写,这意味着这个 OpenJDK 版本与 AOSP 的开发流程紧密相关。 至于压缩包内的文件“openjdk1.7.0_151-amd64”,这很可能是整个 OpenJDK 实现的...

    java-7-openjdk-amd64.tar.gz

    JDK包含了Java运行时环境(JRE)以及开发Java应用程序所需的工具,如编译器(javac)、调试器(jdb)和文档生成器(javadoc)等。 OpenJDK 7的特性包括: 1. **多线程改进**:例如,引入了Fork/Join框架,可以更...

    jdk1.7版本免安装

    在开发环境中,JDK 1.7可以与其他Java版本共存,因为每个版本都有自己的独立的环境变量配置。然而,对于较旧的应用程序,可能需要保持与特定版本的兼容性,所以选择合适的JDK版本至关重要。 总之,JDK 1.7在提升...

    javac.jar

    在 OpenJDK 的 `javac1.7` 版本中,我们可以看到 Java 7 时代的编译技术。这个时期的 Java 已经包含了诸如钻石操作符( Diamond Operator)、多重捕获(Multi-Catch)和静态导入(Static Import)等新特性。通过阅读...

    linux下 Error running javac compiler

    本文详细介绍了在 Linux 系统中解决“Error running javac compiler”错误的具体步骤,包括配置 Apache Ant 环境变量、检查和修复 JDK 的安装与配置等问题。通过这些步骤,可以有效确保 Java 应用程序能够在 Linux ...

    Window版JDK1.7.0_79

    4. 验证安装成功,通过命令行输入`java -version`和`javac -version`检查Java运行时和编译器的版本。 在开发环境中,JDK1.7.0_79可用于编译和运行Java 7及之前的代码,但请注意,随着Java版本的不断更新,某些新...

    jre1.7安装后的文件夹

    虽然题目提及的是JRE,但JDK(Java Development Kit)是包含JRE的,还包括Java编译器(javac)、调试器(jdb)和打包工具(jar)等开发者工具,用于编写、编译和测试Java程序。 总结来说,JRE 1.7安装后的文件夹...

    2_Centos6.5安装jdk,里面有jdk1.6、jdk1.7、jdk1.8,均64位

    在本文中,我们将详细探讨如何在CentOS 6.5操作系统上安装JDK,包括1.6、1.7和1.8这三个64位...同时,考虑使用OpenJDK作为替代方案,它是一个开源的JDK实现,同样兼容Java标准,并且在许多情况下与Oracle JDK性能相当。

    arm64/aarch64架构的 jdk17文件包,linux专用

    它包括Java编译器、调试器、类库和Java运行时环境(JRE)。在这里提到的"jdk17",指的是Java 17版本,这是Oracle公司发布的长期支持(LTS)版本,意味着它将得到更长时间的安全更新和技术支持。 JDK17为开发者带来...

Global site tag (gtag.js) - Google Analytics