为啥要看javac源代码

11 篇文章 0 订阅

前言

本文为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的调试环境

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值