3

如果我从 Oracle JDK 7 源构建自己的rt.jar(称为my-rt.jar) 的修补版本并将其与bootclasspath机制挂钩,如下所示,

$ java -Xbootclasspath/p:/path/to/my-rt.jar -cp /path/to/h2-1.3.174.jar main

然后,我什至无法在我的应用程序开始时加载 H2 驱动程序:

// Application's main.java
public class main {
    public static void main(String[] args) {
        // ...
        Class.forName("org.h2.Driver");      // Line 145

    }

}

以上导致以下异常:

Exception in thread "main" java.lang.ClassNotFoundException: org/h2/Driver
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:190)
        at main.main(main.java:415)

但是,如果我移除-Xbootclasspath/p开关并且其他一切都与以前相同,我可以正常加载驱动程序,并且应用程序的其余部分也可以正常工作。

那么,在 JDBC 驱动程序(例如 H2 的)初始化过程中是否有任何特殊情况阻止我使用 bootclasspath 机制?bootclasspath或者,它不允许加载像 H2 这样的 JDBC 驱动程序的机制有什么特别之处吗?

我没有东西可以尝试了。例如,

  1. 我什至从源代码重新构建了 H2 驱动程序,并确保我的应用程序和驱动程序都使用相同版本的javac.

  2. 我已经从 Eclipse 和命令行尝试了上述方法。

  3. 我已经在两台不同的机器上试过了。

都产生相同的异常。

顺便说一句,我的修补my-rt.jar程序对其进行了非常简单的编辑:它只是public static int counterjava.lang.Object. 在上述Class.forName(...)行之前,我能够验证我确实可以打印启用开关counter时的值。bootclasspath

奇怪的是,即使我注释掉这个counter字段java.lang.Object但继续前置my-rt.jar(这和原来的一样好rt.jar,只是重新编译和前置),即使这样我也无法找到/加载 H2 驱动程序!

(我也在H2 谷歌小组上发布了这个,但那里没有得到回应。也许,那些人不认为这是一个 H2 问题,所以我在这里问。)

4

1 回答 1

1

我已经搞定了。这就是我所做的。

我首先将原件 rt.jar添加到原件 rt.jar之前,如下所示:

$ java -Xbootclasspath/p:/path/to/orig/rt.jar -cp /path/to/h2-1.3.174.jar main

异常消失了!这清楚地告诉我,该bootclasspath/p机制不会干扰 H2 驱动程序的加载。

所以,然后我解开原始文件rt.jardiff用解开的内容编辑它my-rt.jar,我发现大约有 8000 个文件丢失my-rt.jar

$ wc -l *.list
  11285 my-rt.jar.list
  19059 rt.jar.list
  30344 total

所以,很明显,my-rt.jar我从官方那里建造src.zip的东西很多东西都不见了。难怪,H2 驱动程序有加载问题。

为了进一步确认,这次我只复制了我java/lang/Object.class修改后的原始内容rt.jar,你瞧,H2 驱动程序继续加载就好了。

因此,这个名字src.zip是一个可怕的误称。因为它没有构建所需的一切rt.jar,所以应该调用它partial-src.zip(或类似的东西)。

于 2014-01-24T08:56:59.737 回答