java CLASSPATH 无法在命令行上运行
java CLASSPATH not working on command-line
系统详细信息:
Ubuntu 17.10
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.17.10.2-b12)
我无法将我的 java 程序设置为 运行。我不知道为什么它找不到 class。它使用 -classpath
标志编译,但在 运行ning.
时找不到 class
$ 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 .
没有-classpath
的编译不工作(我以为-classpath
默认为.
?)
$ javac Example.java
Example.java:2: error: package javax.mail does not exist
指定 -classpath
有帮助,程序现在编译并生成 Example.class
:
$ javac -classpath javax.mail.jar Example.java
$
这是源代码:
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());
}
}
}
运行 程序产生此错误:
$ 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)
运行 java
没有 -classpath
会导致 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)
为什么 java 找不到示例 class?
我必须设置 -classpath
以包含当前目录。根据documentation classpath
是由:
分隔的。正确的类路径字符串是:
javax.mail.jar:.
下面是一个工作示例。
$ javac -classpath javax.mail.jar:. Example.java
$ java -classpath javax.mail.jar:. Example
Sending...
Email sent!
还有一点需要注意的是,原来在Example.java的顶部有一个package
的定义。我不得不删除它。
您似乎遗漏了一些基本概念。
class路径给出了目录和 JAR 文件的列表,用于搜索所需的 classes。当尝试加载不属于标准库的 class foo.bar.MyClass
时,默认的 classloader 将依次在每个 classpath 元素中查找它,顺序, 直到它找到 class 或用完所有元素。
但是请注意,它按完全限定名称进行搜索。对于作为目录的 classpath 条目,这意味着它会查找相对于目录的 foo/bar/MyClass.class
。对于作为 JAR 文件的 classpath 条目,它会查找相对于 JAR 根目录的 foo/bar/MyClass.class
。属于未命名默认包的 类 有点特殊,或者看起来可能如此,因为它们的 class 文件(例如 InDefaultPackage.class
)预计直接位于根目录中指定JAR或者直接在指定目录下。
Compiling without -classpath
does not work (I thought -classpath
defaulted to .
?)
$ javac Example.java
Example.java:2: error: package javax.mail does not exist
class路径确实默认为.
。这是目录的名称,因此当在 javax.mail
包中搜索 classes 时,它会查找子目录 javax/mail
,如果找到,它会检查class 个文件。请注意,它 不会 进入它在目录树中发现的 JAR 文件。它只在 class 路径中明确命名的那些 JAR 中查找。
错误消息告诉您 javac
根本没有从 javax.mail
包中找到任何 classes。您可以通过在编译 class 路径中指定 JAR(正如您最终所做的那样)或通过在当前目录中解压缩 JAR 来解决它。
Specifying the -classpath
helps, the program now compiles and produces
Example.class:
$ javac -classpath javax.mail.jar Example.java
$
请注意,编译器会将 class 文件存储在与其包相对应的目录结构中,正是 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)
您在回答中阐明,您通过从 Example.java
中删除 package
语句解决了这个问题。没关系,但它并不能真正解释问题,即 java
希望你给它 完全限定的 名称 class。如果 class 在命名包中,则包括包名称。因此,如果 Example.java
包含此包语句:
package com.my;
那么您需要指定给 java
的 class 名称将是 com.my.Example
。您只指定了 Example
,它在默认包中指定了一个名为 "Example" 的 class,您解决 class 未找到问题的方法是移动 class进入默认包。
另请注意,将您的 Java 源文件也放置在与其包结构相匹配的目录结构中是常规且有帮助的。因此,class com.my.Example
的源文件通常位于 com/my/Example.java
中。 Java 编译器将依靠此方案来定位它找不到的 classes 的源代码。
Running java
without -classpath
causes the JNI to not find
javax/mail even though it's in the directory.
$ 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)
不,javax/mail/Address
不在目录中。它在目录中的一个 JAR 文件中。这根本不是一回事,差异很大。
系统详细信息:
Ubuntu 17.10
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.17.10.2-b12)
我无法将我的 java 程序设置为 运行。我不知道为什么它找不到 class。它使用 -classpath
标志编译,但在 运行ning.
$ 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 .
没有-classpath
的编译不工作(我以为-classpath
默认为.
?)
$ javac Example.java
Example.java:2: error: package javax.mail does not exist
指定 -classpath
有帮助,程序现在编译并生成 Example.class
:
$ javac -classpath javax.mail.jar Example.java
$
这是源代码:
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());
}
}
}
运行 程序产生此错误:
$ 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)
运行 java
没有 -classpath
会导致 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)
为什么 java 找不到示例 class?
我必须设置 -classpath
以包含当前目录。根据documentation classpath
是由:
分隔的。正确的类路径字符串是:
javax.mail.jar:.
下面是一个工作示例。
$ javac -classpath javax.mail.jar:. Example.java
$ java -classpath javax.mail.jar:. Example
Sending...
Email sent!
还有一点需要注意的是,原来在Example.java的顶部有一个package
的定义。我不得不删除它。
您似乎遗漏了一些基本概念。
class路径给出了目录和 JAR 文件的列表,用于搜索所需的 classes。当尝试加载不属于标准库的 class foo.bar.MyClass
时,默认的 classloader 将依次在每个 classpath 元素中查找它,顺序, 直到它找到 class 或用完所有元素。
但是请注意,它按完全限定名称进行搜索。对于作为目录的 classpath 条目,这意味着它会查找相对于目录的 foo/bar/MyClass.class
。对于作为 JAR 文件的 classpath 条目,它会查找相对于 JAR 根目录的 foo/bar/MyClass.class
。属于未命名默认包的 类 有点特殊,或者看起来可能如此,因为它们的 class 文件(例如 InDefaultPackage.class
)预计直接位于根目录中指定JAR或者直接在指定目录下。
Compiling without
-classpath
does not work (I thought-classpath
defaulted to.
?)$ javac Example.java Example.java:2: error: package javax.mail does not exist
class路径确实默认为.
。这是目录的名称,因此当在 javax.mail
包中搜索 classes 时,它会查找子目录 javax/mail
,如果找到,它会检查class 个文件。请注意,它 不会 进入它在目录树中发现的 JAR 文件。它只在 class 路径中明确命名的那些 JAR 中查找。
错误消息告诉您 javac
根本没有从 javax.mail
包中找到任何 classes。您可以通过在编译 class 路径中指定 JAR(正如您最终所做的那样)或通过在当前目录中解压缩 JAR 来解决它。
Specifying the
-classpath
helps, the program now compiles and produces Example.class:$ javac -classpath javax.mail.jar Example.java $
请注意,编译器会将 class 文件存储在与其包相对应的目录结构中,正是 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)
您在回答中阐明,您通过从 Example.java
中删除 package
语句解决了这个问题。没关系,但它并不能真正解释问题,即 java
希望你给它 完全限定的 名称 class。如果 class 在命名包中,则包括包名称。因此,如果 Example.java
包含此包语句:
package com.my;
那么您需要指定给 java
的 class 名称将是 com.my.Example
。您只指定了 Example
,它在默认包中指定了一个名为 "Example" 的 class,您解决 class 未找到问题的方法是移动 class进入默认包。
另请注意,将您的 Java 源文件也放置在与其包结构相匹配的目录结构中是常规且有帮助的。因此,class com.my.Example
的源文件通常位于 com/my/Example.java
中。 Java 编译器将依靠此方案来定位它找不到的 classes 的源代码。
Running
java
without-classpath
causes the JNI to not find javax/mail even though it's in the directory.$ 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)
不,javax/mail/Address
不在目录中。它在目录中的一个 JAR 文件中。这根本不是一回事,差异很大。