必威体育Betway必威体育官网
当前位置:首页 > IT技术

为啥要看javac源代码

时间:2019-10-08 16:45:44来源:IT技术作者:seo实验室小编阅读:77次「手机版」
 

java源代码

前言

本文为javac 源码解析的第一篇,主要介绍了如下内如:

  • 阅读javac源代码的好处
  • 阅读javac源代码的储配知识
  • build javac
  • javac源代码结构说明

重要说明: javac是java的编译器,内容高深,非常人所能参透,本人也同样,写本文只为了交流,因此,诸位看客发现纰漏,请指出,点拨一下小弟,不甚感激.

阅读javac源代码的好处

阅读javac的好处如下:

  • 能接触java的真实面貌
  • 能更早的进入到java大神的行列
  • 能够获取到更多面试机会

阅读javac源代码的储配知识

按照官方的说法是: javac读取按照java语法写成的源文件,同时生产字节码文件.其中java语法被The Java Language Specification (JLS) 所定义,字节码文件则被The Java virtual Machine Specification (JVMS) 所定义. 同时,该编译器会处理注解,这是被Pluggable Annotation Processing API (JSR 269). 所定义的. 同样,该编译器还支持 the Java Compiler API (JSR 199). 因此,阅读javac所需要的知识也就很明白了:

  1. JLS
  2. JVMS
  3. (option) JSR 269
  4. (option) JSR 199

另外,既然是一个编译器,自然逃不过编译原理的范畴.

build javac

javac的源代码可以在如下地址中找到: javac源代码.下载下来后,按照 官方说明build说明 进行build即可.

不过,我这里采用的是build jdk的方式构建的.现说明如下:

  1. 在 下载链接 中下载openjdk 8 的源代码.
  2. 由于本人是在mac 上进行构建的,因此需要对源码做如下修改:

    1. 在hotspot/src/share/vm/code/relocInfo.hpp 中,将 datalen = 0 改为 datalen. 如图所示:

      修改1

      搜索 int datalen, 第 462 行,改为 int datalen = 0.如图所示:

      修改2

    2. 在hotspot/src/share/vm/opto/loopPredicate.cpp中,将 _igvn.type(rng)->is_int() >= 0 改成 _igvn.type(rng)->is_int()->_lo >= 0 如图所示:

      修改3

    3. 在hotspot/src/share/vm/runtime/virtualspace.cpp中,将 base() > 0 改成 base() != 0 如图所示:

      修改4

    4. 修改 nashorn/make/BuildNashorn.gmk 中的 第 80 行 -cp 修改为 -Xbootclasspath/p . 如图所示:

      修改5

  3. 然后,创建一个 envsetup.sh, 内容如下:

    \# 设定语言选项,必须设置
    export LANG=C
    \# Mac平台,C编译器不再是GCC,是clang
    export CC=gcc
    \# 跳过clang的一些严格的语法检查,不然会将N多的警告作为ERROR
    export COMPILER_WARNINGS_FATAL=false
    \# 链接时使用的参数
    export LFLAGS='-Xlinker -lstdc++'
    \# 是否使用clang
    export USE_CLANG=true
    \# 使用64位数据模型
    export LP64=1
    \# 告诉编译平台是64位,不然会按32位来编译
    export ARCH_DATA_MODEL=64
    \# 允许自动下载依赖
    export ALLOW_DOWNLOADS=true
    \# 并行编译的线程数,编译时间长,为了不影响其他工作,我选择为2
    export HOTSPOT_BUILD_JOBS=2
    export ALT_parallel_COMPILE_JOBS=2
    \# 是否跳过与先前版本的比较
    export SKIP_COMPARE_IMAGES=true
    \# 是否使用预编译头文件,加快编译速度
    export USE_PRECOMPILED_HEADER=true
    \# 是否使用增量编译
    export INCREMENTAL_BUILD=true
    \# 编译内容
    export BUILD_LANGTOOLS=true
    export BUILD_JAXP=false
    export BUILD_JAXWS=false
    export BUILD_CORBA=false
    export BUILD_HOTSPOT=true
    export BUILD_JDK=true
    \# 编译版本
    export SKIP_DEBUG_BUILD=true
    export SKIP_FASTDEBUG_BUILD=false
    export DEBUG_NAME=debug
    \# 避开javaws和浏览器Java插件之类的部分的build
    export BUILD_DEPLOY=false
    export BUILD_INSTALL=false
    \# 加上产生调试信息时需要的 objcopy
    export OBJCOPY=gobjcopy

    然后,执行 source envsetup.sh

  4. 进行build。

    1. 执行如下命令:

      bash ./configure \
      --with-target-bits=64 \
      --with-debug-level=slowdebug --enable-debug-symbols \
      ZIP_DEBUGINFO_FILES=0
    2. 执行命令:

      make all

    至此,就会看到build 成功的输出

  5. 进行测试,如图所示:

    测试

  6. 添加编译的jdk到Eclipse中,如图所示:

    设置环境变量

  7. 创建一个java 项目,使用我们自己build的jdk.然后将javac的源代码赋值到该项目中, javac的源代码在 openjdk/langtools/src/share/classes/com/sun/tools 下.导入后,如图所示:

    创建项目

  8. 写两个类进行测试,代码如下:

    import com.sun.tools.javac.main.Main;
    public class DebugEntryPoint {
    
        public static void main(String[] args) {
            Main m = new Main("fx_debug");
            m.compile(asArray("/Users/xxxxx/Documents/2017-03-22-brabch/javac-test/src/Demo.java"));
    
        }
    
        private static <T> T[] asArray(T... args) {
            return args;
        }
    }
    public class Demo {
    
        public void foo() {
            char a = 'a';
            a += 32; // 可以通过
        }
    }

    执行后,就可以看到会生成 Demo.class

javac源代码结构说明

用官方的一张图进行说明:

javac

在com.sun.tools.javac下有如下几个包,现说明如下:

1. api –> 实现了JavaCompiler 和javax.tools中其他的api

2. code –> 定义了Java程序的语义元素的表示,如符号、作用域和类型,在javax.lang.model.*.中实现.

3.comp –> 编译器的主要处理阶段,如标记、流分析、“解语法糖”和擦除

4. file –> 使用java.nio.file 的api来访问本地的文件系统.

5. jvm –> 读取和写class文件,生成字节码

6. main –> 编译的主要驱动代码,提供了多样的编译步骤选项

7.model –> javax.lang.model.*. 的额外实现类

8.parser –> 读取java源文件生成语法树

9.processing –> 实现了在javax.annotation.processing.*定义的api

10.resources –> 信息本地化和版本信息的资源文件

11. tree –> 编译器的语法树的表示和实用类,实现了com.sun.source.*.中定义的api

12. util –> 工具

参考链接

compiler-package-overview

compiler-README.html#build

compiler-index

在 macOS 上编译 OpenJDK 8

如何构建javac的调试环境

相关阅读

cmd中javac和java使用及注意事项

一、简述: cmd中,执行java命令与javac命令的区别: javac:是编译命令,将java源文件编译成.class字节码文件。 例如:javac hello.java 将

Javac编译器

 Javac编译器是把 *.java 文件转换为 *.class 文件,是一个前端编译器;对应着有一种把字节码转变为机器码的编译器,称为JIT编译器(Jus

【解决方案】“‘javac’不是内部或外部命令,也不是可

简述 在学着使用Java的命令行来编译java文件的时候,遇到了这个问题Windows操作系统“‘javac’不是内部或外部命令,也不是可运行的

分享到:

栏目导航

推荐阅读

热门阅读