[英]java CLASSPATH not working on command-line
System details: 系统细节:
Ubuntu 17.10
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.17.10.2-b12)
I can't get my java program to run. 我无法运行Java程序。 I don't know why it won't find the class.
我不知道为什么找不到班。 It compiles with the
-classpath
flag, but doesn't find the class when running. 它使用
-classpath
标志进行编译,但是在运行时找不到该类。
$ ls -ltra
total 668
-rw-rw-r-- 1 bvpx bvpx 653275 Jan 19 14:45 javax.mail.jar
drwxr-xr-x 3 bvpx bvpx 4096 Jan 19 14:59 ..
-rw-r--r-- 1 bvpx bvpx 960 Jan 19 15:07 Example.java
drwxr-xr-x 2 bvpx bvpx 4096 Jan 19 15:07 .
Compiling without -classpath
does not work (I thought -classpath
defaulted to .
?) 不带
-classpath
编译不起作用(我认为-classpath
默认为.
?)
$ javac Example.java
Example.java:2: error: package javax.mail does not exist
Specifying the -classpath
helps, the program now compiles and produces Example.class
: 指定
-classpath
帮助,该程序现在编译并生成Example.class
:
$ javac -classpath javax.mail.jar Example.java
$
Here's the source code: 这是源代码:
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
public class Example {
static final int PORT = 587;
/* ... */
public static void main(String[] args) throws Exception {
/* ... */
Transport transport = session.getTransport();
try
{
System.out.println("Sending...");
transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD);
transport.sendMessage(msg, msg.getAllRecipients());
System.out.println("Email sent!");
}
catch (Exception ex) {
System.out.println("Error message: " + ex.getMessage());
}
}
}
Running the program produces this error: 运行程序会产生以下错误:
$ java -Xdiag -classpath javax.mail.jar Example
Error: Could not find or load main class Example
java.lang.ClassNotFoundException: Example
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
Running java
without -classpath
causes the JNI to not find javax/mail
even though it's in the directory. 在不带
-classpath
的情况下运行java
会导致JNI找不到javax/mail
即使它位于目录中也是如此。
$ java -Xdiag Example
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: javax/mail/Address
at java.lang.Class.getDeclaredMethods0(Native Method)
Why can't java find the Example class? Java为什么找不到Example类?
I had to set -classpath
to include the current directory. 我必须设置
-classpath
以包括当前目录。 According to the documentation classpath
is delimited by :
. 根据文档,
classpath
用:
分隔。 The correct classpath string was: 正确的类路径字符串为:
javax.mail.jar:.
Below is a working example. 下面是一个工作示例。
$ javac -classpath javax.mail.jar:. Example.java
$ java -classpath javax.mail.jar:. Example
Sending...
Email sent!
Another thing to note was that there was originally a package
definition at the top of Example.java. 还要注意的另一件事是,Example.java的顶部最初有一个
package
定义。 I had to remove it. 我不得不将其删除。
You seem to be missing some fundamental concepts here. 您似乎在这里缺少了一些基本概念。
The classpath gives a list of directories and JAR files to search for needed classes. 类路径提供了目录和JAR文件的列表,以搜索所需的类。 When trying to load a class
foo.bar.MyClass
that is not part of the standard library, the default classloader will look for it in each classpath element in turn, in order, until it finds the class or runs out of elements. 尝试加载不属于标准库的类
foo.bar.MyClass
,默认的类加载器将依次在每个classpath元素中寻找它,直到找到该类或元素用完为止。
Note well, however, that it searches by fully-qualified name. 但是请注意,它按完全限定的名称进行搜索。 For classpath entries that are directories, that means that it looks for
foo/bar/MyClass.class
relative to the directory. 对于作为目录的类路径条目,这意味着它将查找相对于目录的
foo/bar/MyClass.class
。 For classpath entries that are JAR files, it looks for foo/bar/MyClass.class
relative to the root of the JAR. 对于作为JAR文件的类路径条目,它将查找相对于JAR根目录的
foo/bar/MyClass.class
。 Classes that belong to the unnamed default package are a little special, or so it may seem, because their class files (eg InDefaultPackage.class
) are expected to be located directly in the root of the designated JAR or directly in the specified directory. 属于未命名默认软件包的类似乎有些特殊,因为它们的类文件(例如
InDefaultPackage.class
)应直接位于指定JAR的根目录中或直接位于指定目录中。
Compiling without
-classpath
does not work (I thought-classpath
defaulted to.
?)不带
-classpath
编译不起作用(我认为-classpath
默认为.
?)$ javac Example.java Example.java:2: error: package javax.mail does not exist
The classpath does default to .
classpath 确实默认为
.
. 。 This is the name of a directory, so when searching it for classes in, say, the
javax.mail
package, it looks for a subdirectory javax/mail
, and if that is found, it examines the class files within. 这是目录的名称,因此当在
javax.mail
软件包中搜索类时,它会查找子目录javax/mail
,如果找到了子目录,它将检查其中的类文件。 Note that it does not descend into JAR files it discovers in the directory tree. 请注意,它不会归入它在目录树中发现的JAR文件。 It looks only in those JARs explicitly named in the classpath.
它仅在类路径中显式命名的那些JAR中查找。
The error message is telling you that javac
didn't find any classes at all from the javax.mail
package. 错误消息告诉您
javac
根本没有从javax.mail
包中找到任何类。 You could have solved it either by specifying the JAR in the compilation classpath (as ultimately you did) or by unpacking the JAR in the current directory. 您可以通过在编译类路径中指定JAR(最终还是这样做)或在当前目录中解压缩JAR来解决它。
Specifying the
-classpath
helps, the program now compiles and produces Example.class:指定
-classpath
帮助,该程序现在编译并生成Example.class:$ javac -classpath javax.mail.jar Example.java $
Note that the compiler will store the classfile in a directory structure corresponding to its package, just where the java
command will look for it. 请注意,编译器会将类文件存储在与其包相对应的目录结构中,恰好是
java
命令在其中查找的位置。
Running the program produces this error:
运行程序会产生以下错误:
$ java -Xdiag -classpath javax.mail.jar Example Error: Could not find or load main class Example java.lang.ClassNotFoundException: Example at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
You clarified in your answer that you solved this problem by removing a package
statement from Example.java
. 您在回答中澄清说,通过从
Example.java
删除package
语句解决了此问题。 That's ok, but it doesn't really explain the problem, which is that java
expects you to give it the fully-qualified name of the class. 没关系,但这并不能真正解释问题,这是
java
希望您为其提供类的完全限定名称。 That includes the package name if the class is in a named package. 如果该类在命名包中,则包括包名。 Thus, if
Example.java
contained this package statement: 因此,如果
Example.java
包含以下package语句:
package com.my;
then the class name you would need to specify to java
would be com.my.Example
. 那么您需要为
java
指定的类名称为com.my.Example
。 You specified just Example
, which designates a class named "Example" in the default package, and your solution to the class not found problem was to move your class into the default package. 您只指定了
Example
,它在默认包中指定了一个名为“ Example”的类,而您对该类未找到问题的解决方案是将您的类移到默认包中。
Note also that it is conventional and helpful to lay out your Java source files, too, in a directory structure matching their package structure. 还要注意,将Java源文件布置在与它们的包结构相匹配的目录结构中也是常规且有用的。 Thus, the source file for class
com.my.Example
would conventionally be located in com/my/Example.java
. 因此,类
com.my.Example
的源文件通常位于com/my/Example.java
。 The Java compiler will rely on this scheme to locate sources for classes that it does not find. Java编译器将依靠此方案找到它找不到的类的源。
Running
java
without-classpath
causes the JNI to not find javax/mail even though it's in the directory.在不带
-classpath
的情况下运行java
会导致JNI找不到javax / mail,即使它位于目录中也是如此。$ java -Xdiag Example Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" java.lang.NoClassDefFoundError: javax/mail/Address at java.lang.Class.getDeclaredMethods0(Native Method)
No, javax/mail/Address
was not in the directory. 否,
javax/mail/Address
不在目录中。 It was in a JAR file in the directory. 它在目录中的JAR文件中。 That's not at all the same thing, and the difference is significant.
那根本不是一回事,而且区别是巨大的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.