Java源代码中的“机械生成”java源文件

Posted

技术标签:

【中文标题】Java源代码中的“机械生成”java源文件【英文标题】:"Mechanically generated" java source files in the Java source code 【发布时间】:2014-07-23 07:14:50 【问题描述】:

在查看 Java 源代码时,我发现了一些不寻常的文件,主要与 java.nio 包中的 ByteBuffers 相关,这些文件的源代码非常混乱,并被标记为 This file was mechanically generated: Do not edit!

这些文件还包含大部分空行(有些甚至在 javadocs (!!?) 的中间),大概是为了防止行号发生变化。我还看到了一些 java 反编译器,例如 procyon-decompiler,它们可以选择保留行号,但我怀疑情况是否如此,因为在最终荣誉之前放置空行不会改变任何事情。

这里是其中的一些文件(我在网上找不到指向它们的任何链接,也没有粘贴它们,因为我不想破坏任何版权,但您可以在 src.zip 文件夹中找到它们JDK 安装文件夹的根目录):

java.nio.ByteBuffer java.nio.DirectByteBufferR java.nio.Bits java.nio.BufferOverflowException

我很想知道:

哪些工具生成了这些文件? 为什么该工具保持行号相同?是否让调试(堆栈跟踪)更容易? 为什么要使用工具来生成它们,而所有其他类都是由人类编程的? 为什么该工具会在括号内随机放置空行,在最后的荣誉之前,甚至在 javadocs 中?

【问题讨论】:

我怀疑你会得到答案,因为该代码似乎已经存在了很长时间 - 请查看 this blog post from 2006,当时 Java 仍归 Sun 所有。 这些文件似乎是在构建过程中由一些预处理器从模板文件中生成的:hg.openjdk.java.net/jdk9/dev/jdk/file/3b298c230549/src/share/… IIRC,C 预处理器由于在#if 或#else 之后跳过而插入空行。在这里,我认为基本原理很清楚:如果某些编译器在输出中标记错误,您会在原始输入中找到它。 【参考方案1】:

我可能无法回答所有问题,但一些背景是:

在http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/make/java/nio/Makefile的Makefile中,他们通过一些预处理器从同一个模板文件生成不同的java源文件:

...
$(BUF_GEN)/CharBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
    $(prep-target)
    @$(RM) $@.temp
    TYPE=char SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
    $(MV) $@.temp $@
$(BUF_GEN)/ShortBuffer.java: $(X_BUF_TEMPLATE) $(GEN_BUFFER_SH)
    $(prep-target)
    @$(RM) $@.temp
    TYPE=short SRC=$< DST=$@.temp $(GEN_BUFFER_CMD)
    $(MV) $@.temp $@
...

$(X_BUF_TEMPLATE) 指的是X-Buffer.java.template,这是CharBufferShortBuffer 等类型化缓冲区的来源。

注意:网址将来可能会更改。也很抱歉提到 Java 7 - 在 Java 8 中他们修改了构建系统,到目前为止我没有找到相应的 Makefile。

哪些工具生成了这些文件?

GEN_BUFFER_SH/GEN_BUFFER_CMD最终指向genBuffer.sh,所以创建这些文件的脚本是http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/make/java/nio/genBuffer.sh。

为什么要使用工具来生成它们,而所有其他类都是由人类编程的?

我没有这个具体案例的权威答案,但通常你使用的是代码生成工具

如果您需要创建许多类似的类/方法,它们只是在某些细节上有所不同,但它们足够微妙,以至于您不能使用已建立的机制,如泛型或方法参数(可能是这里的情况,因为缓冲区是为不能与泛型一起使用的原始类型生成) 如果您需要从更简单的表示创建复杂的算法(例如从语法生成解析器)。

为什么该工具保持行号相同?是否让调试(堆栈跟踪)更容易?

我猜:是的,它保留堆栈跟踪中的行号,以便它们与模板文件匹配。 C 预处理器等其他工具的工作原理类似。

【讨论】:

是的,这些类对于原始类型(short、char、...)是多样化的。一个罕见的案例。有一些调查将原始类型包装在一些未来的 java 中,所以你可以有Buffer&lt;int&gt;

以上是关于Java源代码中的“机械生成”java源文件的主要内容,如果未能解决你的问题,请参考以下文章

java 基础

对于java注解的理解

课程总结

mybatis报错:java.lang.IllegalArgumentException: invalid comparison: java.util.Arrays$ArrayList and jav

java中的native关键字

JAVA中的applet是啥?