“ClassNotFoundException” 在尝试运行 .jar 文件时发生。

huangapple go评论49阅读模式
英文:

"ClassNotFoundException" while trying to run .jar file

问题

我有一个 .jar 文件,我是按照 Oracle 文档构建的,使用命令 `jar cfm hangman.jar Manifest.txt src/classes/app/Main.class`。manifest.txt 文件中包含 Main-Class 为 `classes.app.Main`,指示了我的 Main 类的位置。当运行时,抛出 ClassNotFoundException,表示找不到 `classes.app.Main`。我需要帮助理解问题出在哪里。是主类有问题还是缺少了类路径呢?
<br>
<br>
这是项目树结构:

.
├── hangman.jar
├── Manifest.txt
├── README.md
└── src
├── app
│ ├── Main.java
│ ├── Player.java
│ ├── Players.java
│ ├── Play.java
│ ├── Themes.java
│ ├── Word.java
│ └── Words.java
└── classes
└── app
├── Main.class
├── Play.class
├── Player.class
├── Players.class
├── Themes.class
├── Word.class
└── Words.class

英文:

I have a .jar that I built following the Oracle docs, using jar cfm hangman.jar Manifest.txt src/classes/app/Main.class. The manifest.txt file contains Main-Class as classes.app.Main, telling where my Main class is. When executed, ClassNotFoundException is thrown, saying it couldn't find classes.app.Main. I need help trying to understand what's wrong here. Is it the main class or maybe a missing classpath?
<br>
<br>
Here's the project tree:

.
├── hangman.jar
├── Manifest.txt
├── README.md
└── src
    ├── app
    │&#160;&#160; ├── Main.java
    │&#160;&#160; ├── Player.java
    │&#160;&#160; ├── Players.java
    │&#160;&#160; ├── Play.java
    │&#160;&#160; ├── Themes.java
    │&#160;&#160; ├── Word.java
    │&#160;&#160; └── Words.java
    └── classes
        └── app
            ├── Main.class
            ├── Play.class
            ├── Player.class
            ├── Players.class
            ├── Themes.class
            ├── Word.class
            └── Words.class


答案1

得分: 2

你没有展示代码,但极有可能你的类的包名只是app,而不是classes.app,而且classes只是一个目录名,用来存放类文件,实际上并不是包层次结构的一部分。在jar文件中,类文件的条目名称,或者相对于类路径目录的类文件名称,必须与包层次结构(如果有的话)以及类名和后缀.class完全相等,不能添加或删除任何内容。这意味着你的jar文件应该通过以下方式创建:进入classes目录,然后相对于该目录添加文件

jar cfm hangman.jar Manifest.txt -C classes app/Main.class

并且清单中的Main-class条目应为app.Main。如果你只需要清单中的Main-class而不需要其他任何内容(除了版本信息,如果我没记错的话),你可以让jar命令为你创建清单:

jar cfe hangman.jar app.Main -C classes app/Main.class

另外我注意到你的源代码树中还有其他类。如果这些类从Main类中直接或间接地被调用或引用(即嵌套类),它们也必须包含在jar文件中。你可能想要使用app/*来指定,虽然可能你想要或者甚至需要更有选择性。

元信息:我以为标准教程中已经涵盖了这一点,但虽然大部分内容都在,但它们并没有在我能找到和参考的任何地方真正地整合在一起。

英文:

You don't show the code, but it is extremely likely that the package for your class is just app not classes.app, and classes is only a directory name to contain the class files, not actually part of the package hierarchy. The name of a class file entry in a jar, OR the name of a class file relative to a classpath directory, must be exactly a directory path equal to the package hierarchy (if any) plus the class name and the suffix .class, with nothing added or removed. This means your jar should be created by going to the classes directory and then adding the file(s) relative to that directory:

 jar cfm hangman.jar Manifest.txt -C classes app/Main.class 

and the Main-class entry in the manifest should be app.Main. If you only need main-class in the manifest and nothing else (except version, IIRC), you can have jar create it for you:

 jar cfe hangman.jar app.Main -C classes app/Main.class

Also I note that there are other classes in your source tree. If these classes are called or referenced from the Main class, directly or indirectly (i.e. nested), they must also be in the jar. You probably want to use app/* instead, although it is possible you want or even need to be more selective.

Meta: I thought this was covered in the standard tutorial, but although most of the pieces are there they aren't really pulled together anyplace I could find and refer to.

huangapple
  • 本文由 发表于 2020年9月24日 05:12:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64036306.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定