java类路径在命令行上不工作

java类路径在命令行上不工作,java,linux,ubuntu,classpath,javac,Java,Linux,Ubuntu,Classpath,Javac,系统详细信息: 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程序运行。我不知道为什么找不到班级。它使用-classpath标志进行编译,但在运行时找不到该类 $ ls -ltra total 668 -rw-rw-r-- 1 bvpx bvpx 653275 Jan 19 14:45

系统详细信息:

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程序运行。我不知道为什么找不到班级。它使用
-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 .
没有
-classpath
的编译不起作用(我认为
-classpath
默认为
?)

指定
-classpath
有帮助,程序现在编译并生成
示例。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 -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 -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找不到示例类?

我必须设置
-classpath
以包含当前目录。根据
类,路径
分隔。正确的类路径字符串为:

javax.mail.jar:.
下面是一个工作示例

$ javac -classpath javax.mail.jar:. Example.java  
$ java -classpath javax.mail.jar:. Example 
Sending...
Email sent!

另外需要注意的是,Example.java的顶部最初有一个
定义。我必须删除它。

我必须设置
-classpath
以包含当前目录。根据
类,路径
分隔。正确的类路径字符串为:

javax.mail.jar:.
下面是一个工作示例

$ javac -classpath javax.mail.jar:. Example.java  
$ java -classpath javax.mail.jar:. Example 
Sending...
Email sent!

另外需要注意的是,Example.java的顶部最初有一个
定义。我不得不删除它。

您似乎缺少一些基本概念

类路径提供了一个目录和JAR文件列表,用于搜索所需的类。当尝试加载不属于标准库的类
foo.bar.MyClass
时,默认类加载器将依次在每个类路径元素中查找该类,直到找到该类或元素用尽为止

但是,请注意,它按完全限定名进行搜索。对于作为目录的类路径条目,这意味着它查找相对于目录的
foo/bar/MyClass.class
。对于属于JAR文件的类路径条目,它查找相对于JAR根的
foo/bar/MyClass.class
。属于未命名默认包的类有点特殊,或者看起来是这样,因为它们的类文件(例如,
InDefaultPackage.class
)应该直接位于指定JAR的根目录中,或者直接位于指定的目录中

$ 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 -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)
没有
-classpath
的编译不起作用(我认为
-classpath
默认为
?)

类路径默认为
。这是一个目录的名称,因此当在
javax.mail
包中搜索类时,它会查找子目录
javax/mail
,如果找到子目录,它会检查其中的类文件。注意,它不会下降到它在目录树中发现的JAR文件中。它只在类路径中显式命名的jar中查找

错误消息告诉您,
javac
javax.mail
包中根本找不到任何类。您可以通过在编译类路径中指定JAR(正如最终所做的那样)或在当前目录中解压JAR来解决这个问题

$ 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 -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)
指定
-classpath
有帮助,程序现在编译并生成 示例.class:

$ javac -classpath javax.mail.jar Example.java
$
请注意,编译器将类文件存储在与其包对应的目录结构中,而
java
命令将在其中查找它

运行该程序会产生以下错误:

$ 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 -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
希望您为它提供类的完全限定名。如果类位于命名包中,则包含包名。因此,如果
Example.java
包含以下包语句:

package com.my;
然后需要指定给
java
的类名将是
com.my.Example
。您只指定了
Example
,它在默认包中指定了一个名为“Example”的类,而解决未找到类问题的方法是将类移动到默认包中

还要注意的是,在与Java源文件的包结构相匹配的目录结构中布局Java源文件也是一种常规做法,也是很有帮助的。因此,类
com.my.Example
的源文件通常位于
com/my/Example.java
中。Java编译器将依赖此方案来定位它找不到的类的源代码

运行
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 -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文件中。这完全是两码事,差别很大。

您似乎遗漏了一些基本概念

类路径提供了一个目录和JAR文件列表,用于搜索所需的类。当尝试加载不属于标准库的类
foo.bar.MyClass
时,默认类加载器将依次在每个类路径元素中查找该类,直到找到该类或元素用尽为止

但是,请注意,它按完全限定名进行搜索。对于作为目录的类路径条目,这意味着它查找相对于目录的
foo/bar/MyClass.class
。对于属于JAR文件的类路径条目,它查找相对于JAR根的
foo/bar/MyClass.class
。属于未命名默认包的类有点特殊,或者看起来是这样,因为它们的类文件(例如
InDefaultPackage.class
)是