# wrong, FQN is needed
java Foon
# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon
# wrong, similar to above
java -classpath . com.acme.example.Foon
# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon
# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon
1条答案
按热度按时间wdebmtf21#
java命令语法
首先,您需要了解使用
java
(或javaw
)命令。正常的语法1是这样的:
哪里
<option>
是命令行选项(以“-”字符开头),<class-name>
是完全限定的java类名,并且<arg>
是传递给应用程序的任意命令行参数。1-还有一些其他的语法,在这个答案的末尾描述。
该类的完全限定名(fqn)按照惯例是用java源代码编写的;例如
但是有些版本的
java
命令允许您使用斜杠而不是句点;例如它看起来像一个文件路径名,但不是。请注意,术语完全限定名是标准的java术语。。。不是我为了迷惑你而编造的:-)
下面是一个例子
java
命令应如下所示:以上将导致
java
命令执行以下操作:搜索已编译版本的
com.acme.example.ListUsers
班级。加载类。
检查类是否有
main
方法的签名、返回类型和修饰符由public static void main(String[])
. (注意,方法参数的名称不是签名的一部分。)将命令行参数(“fred”、“joe”、“bert”)作为
String[]
.java找不到类的原因
当您收到消息“找不到或加载主类…”时,这意味着第一步失败。这个
java
命令无法找到类。实际上,消息中的“…”将是java
正在寻找。那为什么它找不到班级呢?
原因#1-您在classname参数中犯了一个错误
第一个可能的原因是您可能提供了错误的类名(或者。。。正确的类名,但格式错误。)考虑到上面的示例,这里有多种错误的方法来指定类名:
示例#1-简单的类名:
当类在包中声明时,例如
com.acme.example
,则必须在java
指挥部;例如示例#2-文件名或路径名而不是类名:
示例#3-大小写不正确的类名:
示例#4-打字错误
示例#5-源文件名(java 11或更高版本除外;(见下文)
示例#6-您完全忘记了类名
原因#2-应用程序的类路径指定不正确
第二个可能的原因是类名是正确的,但是
java
命令找不到类。要理解这一点,您需要理解“类路径”的概念。oracle文档很好地解释了这一点:这个
java
命令文档设置类路径。
java教程-路径和类路径
所以。。。如果正确指定了类名,接下来要检查的是是否正确指定了类路径:
阅读上面链接的三个文档(对。。。读读它们!java程序员至少要了解java类路径机制的基本工作原理,这一点很重要。)
查看命令行和/或运行
java
命令。检查目录名和jar文件名是否正确。如果类路径中有相对路径名,请检查它们是否正确解析。。。从运行
java
命令。检查类(错误消息中提到的)是否可以位于有效的类路径上。
请注意,windows与linux和macos的类路径语法不同(类路径分隔符是
;
在windows和:
在其他人身上。如果您为您的平台使用了错误的分隔符,您将不会得到明确的错误消息。相反,您将在路径上得到一个不存在的文件或目录,该文件或目录将被静默忽略。)原因#2a-类路径上的目录错误
当您将目录放在类路径上时,它在概念上对应于限定名称空间的根。通过将完全限定名Map到路径名,类位于该根下的目录结构中。例如,如果“/usr/local/acme/classes”在类路径上,那么当jvm查找一个名为
com.acme.example.Foon
,它将查找具有以下路径名的“.class”文件:如果将“/usr/local/acme/classes/com/acme/example”放在类路径上,那么jvm将无法找到类。
原因#2b-子目录路径与fqn不匹配
如果你的班级fqn是
com.acme.example.Foon
,然后jvm将在目录“com/acme/example”中查找“foon.class”:如果您的目录结构与按照上述模式命名的包不匹配,jvm将找不到您的类。
如果您试图通过移动类来重命名它,那么也会失败。。。但是异常stacktrace会有所不同。可以这样说:
因为类文件中的fqn与类加载器期望的结果不匹配。
举一个具体的例子,假设:
你想跑吗
com.acme.example.Foon
班级,完整文件路径为
/usr/local/acme/classes/com/acme/example/Foon.class
,您当前的工作目录是
/usr/local/acme/classes/com/acme/example/
,然后:
笔记:
这个
-classpath
选项可以缩短为-cp
在大多数java版本中。检查相应的手动条目java
,javac
等等。在类路径中选择绝对路径名和相对路径名时,请仔细考虑。请记住,如果当前目录发生更改,相对路径名可能会“中断”。
原因#2c-类路径中缺少依赖项
类路径需要包含应用程序所依赖的所有其他(非系统)类(系统类是自动定位的,您很少需要关心这一点。)为了正确加载主类,jvm需要找到:
班级本身。
超类层次结构中的所有类和接口(例如,请参见类路径中存在java类,但启动失败并出现错误:找不到或加载主类)
通过变量或变量声明、方法调用或字段访问表达式引用的所有类和接口。
(注意:jls和jvm规范允许jvm在某些范围内“延迟”加载类,这可能会影响抛出类加载器异常的时间。)
原因#3-类在错误的包中声明
偶尔会有人将源代码文件放进源代码树中的错误文件夹,或者忽略了
package
宣言。如果您在ide中这样做,ide的编译器会立即告诉您这一点。类似地,如果您使用一个像样的java构建工具,该工具将运行javac
以检测问题的方式。但是,如果您手工构建java代码,您可以这样做:编译器不会注意到问题,并且生成的“.class”文件不在您期望的位置。还是找不到问题?
检查的东西很多,很容易漏掉。尝试添加
-Xdiag
选择java
命令行(作为java
). 它将输出有关类加载的各种信息,这可能会为您提供真正问题的线索。此外,请考虑从网站、文档等复制和粘贴不可见或非ascii字符可能导致的问题。想想“同形文字”,两个字母或符号看起来一样。。。但他们不是。
最后,如果您试图从中带有错误签名的jar文件启动,显然会遇到这个问题
(META-INF/*.SF)
或者如果在MANIFEST.MF
文件(参见https://stackoverflow.com/a/67145190/139985).java的可选语法
对于使用
java command
.用于启动“可执行”jar文件的语法如下:
例如
入口点类的名称(即。
com.acme.example.ListUser
)类路径在jar文件的清单中指定。从模块(java 9及更高版本)启动应用程序的语法如下:
入口点类的名称由
<module>
或者由可选的<mainclass>
.从java 11开始,您可以编译和运行单个源代码文件,并使用以下语法运行它:
哪里
<sourcefile>
是(通常)后缀为“.java”的文件。有关更多详细信息,请参阅
java
您正在使用的java版本的命令。IDE公司
典型的javaide支持在idejvm本身或子jvm中运行java应用程序。它们通常不受这个特殊异常的影响,因为ide使用自己的机制来构造运行时类路径、标识主类和创建
java
命令行。但是,如果您在ide后面做一些事情,仍然有可能发生这种异常。例如,如果您以前在eclipse中为java应用程序设置了一个应用程序启动程序,然后将包含“main”类的jar文件移动到文件系统中的另一个位置,而没有告诉eclipse,那么eclipse会在不知情的情况下使用不正确的类路径启动jvm。
简而言之,如果您在ide中遇到这个问题,请检查诸如过时ide状态、损坏的项目引用或损坏的启动程序配置之类的情况。
ide也有可能会简单地混淆。ide'