英文:
"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
│   ├── 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
答案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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论