JDK 自带的编译器可以在程序里直接调用:源码字符串进、class 字节出。这篇真实运行内存编译与加载、诊断信息、警告选项、--release 的限制,以及运行时里缺少 jdk.compiler 时是什么表现。
第一次编译:成功 = true,耗时 150 ms,诊断 0 条 内存里得到的 class:[demo.Hello$Inner, demo.Hello],字节数 [269, 381] 用自定义 ClassLoader 加载并调用 applyAsInt(20) = 41,c.getClassLoader() 是 Main 的类加载器吗 = false,名字 = demo.Hello 之后连续编译同一段代码 10 次的耗时(ms):[19, 15, 13, 12, 11, 10, 10, 10, 10, 8]
编译有错的代码:成功 = false,class 产出 0 个,诊断 3 条
ERROR 第 3 行第 13 列 code=compiler.err.prob.found.req:incompatible types: java.lang.String cannot be converted to int
ERROR 第 4 行第 5 列 code=compiler.err.cant.resolve.location.args:cannot find symbol
ERROR 第 5 行第 16 列 code=compiler.err.cant.resolve.location:cannot find symbol
默认选项编译带原始类型的代码:诊断 [NOTE:compiler.note.unchecked.filename, NOTE:compiler.note.unchecked.recompile]
加 -Xlint:all:诊断 [WARNING:compiler.warn.raw.class.use, WARNING:compiler.warn.raw.class.use, MANDATORY_WARNING:compiler.warn.unchecked.call.mbr.of.raw.type]
再加 -Werror:成功 = false,诊断 [WARNING:compiler.warn.raw.class.use, WARNING:compiler.warn.raw.class.use, MANDATORY_WARNING:compiler.warn.unchecked.call.mbr.of.raw.type, ERROR:compiler.err.warnings.and.werror]--release 8 成功 = true,class 文件主版本号 = 52(Java 8) --release 17 成功 = true,class 文件主版本号 = 61(Java 17) --release 21 成功 = true,class 文件主版本号 = 65(Java 21) --release 11 编译 record:成功 = false,[records are not supported in -source 11] --release 21 引用 sun.misc.Unsafe 构造器:成功 = false,[ERROR:Unsafe() has private access in sun.misc.Unsafe] --release 11 使用 List.getFirst()(Java 21 才有的 API):成功 = false,错误:cannot find symbol --release 17 使用 List.getFirst()(Java 21 才有的 API):成功 = false,错误:cannot find symbol --release 21 使用 List.getFirst()(Java 21 才有的 API):成功 = true warning: [options] source value 8 is obsolete and will be removed in a future release warning: [options] target value 8 is obsolete and will be removed in a future release warning: [options] To suppress warnings about obsolete options, use -Xlint:-options. 3 warnings
用完整 JDK 编译 Main:rc=0 jlink --add-modules java.base(运行时 47 MB):rc=1 Exception in thread "main" java.lang.NoClassDefFoundError: javax/tools/ToolProvider; at Main.main(Main.java:1) jlink --add-modules java.base,java.compiler(运行时 48 MB):rc=0 ToolProvider.getSystemJavaCompiler() = null jlink --add-modules java.base,java.compiler,jdk.compiler(运行时 67 MB):rc=0 ToolProvider.getSystemJavaCompiler() = com.sun.tools.javac.api.JavacTool@ba4d54 完整 JDK 21 目录大小 350 MB