java CLASSPATH无法在命令行上运行

时间:2018-01-19 20:19:41

标签: 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 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不能找到Example类?

2 个答案:

答案 0 :(得分:2)

我必须将-classpath设置为包含当前目录。根据{{​​3}} classpath:分隔。正确的类路径字符串是:

javax.mail.jar:.

以下是一个工作示例。

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

另一件需要注意的事情是,Example.java顶部最初有一个package定义。我不得不将其删除。

答案 1 :(得分:1)

这里似乎缺少一些基本概念。

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

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

  

不使用-classpath进行编译无效(我认为-classpath   默认为.?)

$ javac Example.java 
Example.java:2: error: package javax.mail does not exist

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

错误消息告诉您javac根本没有找到javax.mail包中的任何类。您可以通过在编译类路径中指定JAR(最终完成)或通过在当前目录中解压缩JAR来解决它。

  

指定-classpath帮助,程序现在编译并生成   Example.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)

您在答案中澄清说,您通过从package删除Example.java声明来解决此问题。没关系,但它并没有真正解释这个问题,java希望你给它提供类的完全限定的名称。如果类在命名包中,则包括包名。因此,如果Example.java包含此包语句:

package com.my;

然后您需要指定给java的类名称为com.my.Example。您只指定了Example,它指定了一个名为&#34的类;示例"在默认包中,您找到类的问题的解决方案是将您的类移动到默认包中。

另请注意,将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)

不,目录中的javax/mail/Address 不是。它位于目录中的JAR文件中。这根本不是一回事,差别很大。