在引导类路径中复制 jar 文件不起作用

2022-09-02 13:45:50

A 有一个 Java 代码作为:

public class Hello
{
        public void print()
        {
                System.out.println("Hi");
        }
}

我编译了它并创建了一个Hello.class。我把它添加到Jar文件中,你好.jar作为:

$jar -cvf hello.jar Hello.class

我又写了一个程序:

class Test1
{
        public static void main(String[] args)
        {
                new Hello().print();
                System.out.println(Hello.class.getClassLoader());
        }
}

并从当前目录中删除了Hello.class。

然后我在扩展类路径中复制了hello.jar。我的程序工作正常,因为:

$sudo cp hello.jar /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext
$ java Test1
Hi
sun.misc.Launcher$ExtClassLoader@28d93b30
$ 

如果我从扩展类路径中删除hello.jar并将其复制到boot strap类路径(usr/lib/jvm/java-8-openjdk-amd64/jre/lib/)中,其中也包含rt.jar,那么我的程序就无法正常工作。

$ java Test1
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
    at Test1.main(Test1.java:5)
Caused by: java.lang.ClassNotFoundException: Hello
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

据我所知,引导或扩展类装入器中的所有jar文件都可以在程序中使用。如果 Java 是正确的,为什么会抛出该异常?如果我不正确,那么请指导我。


答案 1

默认情况下,Bootstrap类是非常具体的,它们只包括的类和其他几个重要的jar文件,因为它受到保护,并不意味着扩展,只有扩展类意味着通过将jar文件添加到.rt.jarjre/lib/ext/

但是,您可以通过启动JVM来修改在Open JDK上定义Bootstrap类的类路径,如下所示:

java -Xbootclasspath/a:"/path/to/my/folder/classes" Test1

-Xbootclasspath/a:path

指定要追加到缺省引导类路径的以冒号分隔的指导路径、JAR 存档和 ZIP 存档。

-Xbootclasspath/p:path

指定以冒号分隔的引导路径、JAR 归档文件和 ZIP 归档文件,以预置在缺省引导类路径的前面。注: 不应部署此选项以重写 rt.jar 中的类的应用程序,因为这样做会违反 Java 2 运行时环境二进制代码许可证。

下面是一个具体示例 https://wiki.openjdk.java.net/display/mlvm/BootClassPath


答案 2

我使用的是java 7而不是8,我希望这适用于所有版本的java。

在java 7中,如果你去这个lib文件夹,你可以看到一个名为classlist的文件,如果你打开它,你可以看到所有的基本类都列在那里(大约2202个类)。这些类是从 lib 文件夹中的所有 jar 文件加载的。这些文件夹仅包含 JAVA API。因此,为了访问您的jar,您必须将其包含在classlist文件中


推荐