尽管设置了类路径,但 Java NoClassDefFoundError

发布于 2024-11-10 10:15:54 字数 2869 浏览 3 评论 0原文

我在让 Java 应用程序在控制台和/或使用 Ant 中运行时遇到一些麻烦。 我知道很多开始问题都与类路径未设置或设置不正确有关,尽管我相当确定我设置正确,所以我的搜索仅产生了相关结果。

这是我的应用程序的一般设置: 类位于模型、视图和控制器包中。 controller.Controller 是具有 main 方法的类。我使用 objectdb 作为我的 JPA 提供程序。

我正在使用 Ant 来编译我的应用程序。

编译后,我可以使用以下脚本从 ant 运行我的应用程序:

<target name="run" description="default build process">
    <java fork="true" classname="${main-class}">
        <classpath>
            <path refid="classpath" />
        </classpath>
    </java>
</target>

其中 ${main-class} 是controller.Controller,类路径由 /lib 和 /dist 文件夹组成(应用程序的 jar 文件被编译到 /dist)

现在我尝试了将所有 .jar 文件从 /lib 和 /dist 复制到一个单独的文件夹,并使用 java -jar Cooking.jar -cp . 运行它们,这会导致

Exception in thread "main" java.lang.NoClassDefFoundError: javax/persistence/Persistence
    at model.jpa.JPAModelFactory.<init>(JPAModelFactory.java:28)
    at model.jpa.JPAModelFactory.<init>(JPAModelFactory.java:24)
    at controller.Controller.<init>(Controller.java:59)
    at controller.Controller.main(Controller.java:116)
Caused by: java.lang.ClassNotFoundException: javax.persistence.Persistence
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 4 more

所以我尝试了 ant 并稍微修改了上面的构建目标:

<target name="run2" description="default build process">
    <java fork="true" jar="${dist.dir}/${ant.project.name}.jar">
        <classpath>
            <path refid="classpath" />
        </classpath>
    </java>
</target>

这会导致同样的错误。我不明白为什么。

为了测试它,我尝试通过直接指定主类从命令行运行: java -cp 。由于某种原因,controller.Controller 甚至无法找到该类(它就在那里,我确认了它):

Exception in thread "main" java.lang.NoClassDefFoundError: controller/Controller
Caused by: java.lang.ClassNotFoundException: controller.Controller
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: controller.Controller.  Program will exit.

我已将 JAVA_HOME 设置为我的 JDK 路径,将 CLASSPATH 设置为我的 JRE 的/lib 路径。 操作系统是Windows 7 64位,Java版本是1.6.0_25-b06

我对两件事感到困惑: a) 为什么Java无法找到controller.Controller,即使它存在于.jar文件中并且.jar文件位于当前目录中? b) 我做错了什么,用 -jar 调用 Java 似乎搞乱了查找机制。

非常感谢任何帮助。

I have some trouble with getting a Java application to run in the console and/or with Ant.
I know that a lot of starting issues are related to the classpath being not set or incorrectly set, though I'm fairly sure I set it correctly, so my search only yielded results on that.

Here is the general setup of my application:
classes are in packages model, view and controller. controller.Controller is the class with the main method. I am using objectdb as my JPA provider.

I am using Ant to compile my application.

After compiling, I can run my application from ant with the following script:

<target name="run" description="default build process">
    <java fork="true" classname="${main-class}">
        <classpath>
            <path refid="classpath" />
        </classpath>
    </java>
</target>

where ${main-class} is controller.Controller and classpath consists of /lib and /dist folders (the application's jar file is compiled to /dist)

Now I tried copying all .jar files from /lib and /dist to one separate folder and run them withjava -jar cooking.jar -cp . which results in

Exception in thread "main" java.lang.NoClassDefFoundError: javax/persistence/Persistence
    at model.jpa.JPAModelFactory.<init>(JPAModelFactory.java:28)
    at model.jpa.JPAModelFactory.<init>(JPAModelFactory.java:24)
    at controller.Controller.<init>(Controller.java:59)
    at controller.Controller.main(Controller.java:116)
Caused by: java.lang.ClassNotFoundException: javax.persistence.Persistence
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 4 more

So I tried ant and slightly modified above build target to:

<target name="run2" description="default build process">
    <java fork="true" jar="${dist.dir}/${ant.project.name}.jar">
        <classpath>
            <path refid="classpath" />
        </classpath>
    </java>
</target>

which results in the same error. I don't understand why.

Just to test it, I tried running from the command line by specifying the main class directly: java -cp . controller.Controller which for some reason cannot even locate the class (it's there, I confirmed it):

Exception in thread "main" java.lang.NoClassDefFoundError: controller/Controller
Caused by: java.lang.ClassNotFoundException: controller.Controller
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
Could not find the main class: controller.Controller.  Program will exit.

I have set JAVA_HOME to my JDK's path, and CLASSPATH to my JRE's/lib path.
OS is Windows 7 64 bit, Java version is 1.6.0_25-b06

I am puzzled by two things:
a) Why is Java unable to locate controller.Controller, even though it is present in the .jar file and the .jar file is in the current directory?
b) What am I doing wrong that calling Java with -jar seems to mess up the lookup mechanisms.

Any help is highly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瀟灑尐姊 2024-11-17 10:15:54

类路径应由

  1. 包含类文件(在其正确的包目录中)
  2. jar 文件的目录组成。

您不能将类路径指向 jar 目录。运行应用程序服务器(例如 Tomcat)时情况有所不同,它会为您从目录加载 jar。

The class path should consist of

  1. directories with class files (in their proper package directory)
  2. jar files.

You cannot point the class path to a directory of jars. Things are different when running a application server (eg Tomcat), which will load jars from a directory for you.

差↓一点笑了 2024-11-17 10:15:54

虽然我相当确定我设置正确

证据对你不利。 JVM 告诉你你没有正确设置它。

您认为 ref 'classpath' 指向什么?您认为它的值来自哪里?它们应该在 Ant build.xml 中定义,对吧?像这样:

<path id="production.class.path">
    <pathelement location="${production.classes}"/>
    <pathelement location="${production.resources}"/>
    <fileset dir="${production.lib}">
        <include name="**/*.jar"/>
        <exclude name="**/junit*.jar"/>
        <exclude name="**/*test*.jar"/>
    </fileset>
</path>

<path id="test.class.path">                            
    <path refid="production.class.path"/>
    <pathelement location="${test.classes}"/>
    <pathelement location="${test.resources}"/>
    <fileset dir="${test.lib}">
        <include name="**/junit*.jar"/>
        <include name="**/*test*.jar"/>
    </fileset>
</path>

如果您正在创建可执行 JAR,则需要在清单中指定主类和类路径,正如 CoolBeans 在注释中正确指出的那样。 3rd 方 JAR 位置必须相对于可执行 JAR。您应该将它们与可执行 JAR 一起打包,以便相对路径易于整理和理解。

though I'm fairly sure I set it correctly

The evidence is against you. The JVM is telling you that you have not set it correctly.

What do you think that ref 'classpath' pointing to? Where do you assume its values are coming from? They should be defined inside the Ant build.xml, right? Like this:

<path id="production.class.path">
    <pathelement location="${production.classes}"/>
    <pathelement location="${production.resources}"/>
    <fileset dir="${production.lib}">
        <include name="**/*.jar"/>
        <exclude name="**/junit*.jar"/>
        <exclude name="**/*test*.jar"/>
    </fileset>
</path>

<path id="test.class.path">                            
    <path refid="production.class.path"/>
    <pathelement location="${test.classes}"/>
    <pathelement location="${test.resources}"/>
    <fileset dir="${test.lib}">
        <include name="**/junit*.jar"/>
        <include name="**/*test*.jar"/>
    </fileset>
</path>

If you're creating an executable JAR, you need to specify the main class and classpath in the manifest, as CoolBeans correctly pointed out in the comment. The 3rd party JAR locations have to be relative to the executable JAR. You should package them with your executable JAR in such a way that the relative path is easy to sort out and understand.

走野 2024-11-17 10:15:54

我发现当我在目标中指定两者 jar="..." 时会发生这种情况。我删除了 jar="...",将 .jar 放入 列表中,然后运行。

I've found this happens when I specify both the <classpath> and the jar="..." in the target. I removed the jar="...", placed that .jar into the <classpath> list and it ran after that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文