12

在 Jigsaw 之前,在 OpenJDK 中替换一个或多个类非常容易(执行一些测试或做出贡献)。我可以从 OpenJDK 源中复制一个原始文件,例如,复制java/util/ArrayList.javasrc/java/util/中,添加我想要的任何更改,然后正常编译它(输出到mypatch目录):

$ javac.exe src\java\util\ArrayList.java -d mypatch

之后,我可以启动 JVM来用打补丁-Xbootclasspath/p的替换原来的:ArrayList

$ java -Xbootclasspath/p:mypatch MyTestClass

然而,自从 Java 9-ea+111 中的 Jigsaw 集成以来,这不再起作用。编译命令报告大量错误,如下所示:

src\java\util\ArrayList.java:26: error: package exists in another module: java.base
package java.util;
^
src\java\util\ArrayList.java:108: error: cannot find symbol
public class ArrayList<E> extends AbstractList<E>
                                  ^
  symbol: class AbstractList
src\java\util\ArrayList.java:109: error: cannot find symbol
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
                   ^

即使我使用旧版 JDK 编译,JVM 也无法启动:

-Xbootclasspath/p is no longer a supported option.
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

如何使用 Jigsaw 为 JDK 打补丁?

4

2 回答 2

12

从 javac 错误信息可以知道你正在编译的类属于java.base模块。现在要编译 JDK 类,您必须使用参数指定它所属的模块--patch-module

$ javac --patch-module java.base=src -d mypatch \
      src/java.base/java/util/ArrayList.java

现在用新的类替换现有的类,使用--patch-module <module-name>JVM 参数:

$ java --patch-module java.base=mypatch MyTestClass

在这里,我们应该指定包含与相应模块命名的子目录的目录。现在一切都像以前一样工作。如果您修补了多个模块,则可以多次指定:

$ java --patch-module java.base=mypatch --patch-module java.xml=myxmlpatch MyTestClass
于 2016-03-28T20:31:34.177 回答
3

这是适用于已发布版本的 jdk 9 的新解决方案。

javac --patch-module java.base=src -d mypatches/java.base \
    src/java.base/java/util/ArrayList.java

java --patch-module java.base=mypatches/java.base ...

来源:Project Jigsaw:模块系统快速入门指南

于 2017-10-10T04:50:39.490 回答