从子文件夹导入包:线程异常 "main" java.lang.NoClassDefFoundError

Import package from subfolder: Exception in thread "main" java.lang.NoClassDefFoundError

我有这个目录结构:

src
  MyPackageFile1.java
  MyPackageFile2.java
vendor
  something.jar
Example.java

请注意,src 下的所有文件都有一个 package com.example; 声明,而 Example.java 不属于该包:它是该包的用法示例(因此它有 import xyz.pushpad.*;).

我成功编译了:

javac -classpath vendor/something.jar src/*.java Example.java 

然而当我运行:

java Example

我得到:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: com/example/DeliveryException
  at java.lang.Class.getDeclaredMethods0(Native Method)
  at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
  at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
  at java.lang.Class.getMethod0(Class.java:3018)
  at java.lang.Class.getMethod(Class.java:1784)
  at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
  at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: com.example.MyPackageFile1
  at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
  at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
  ... 7 more

与编译命令类似,运行命令也需要类路径中的 jar 文件

java -cp vendor/something.jar;src com.example.Example

其中 Example.java 移动到新目录 src/com/something

如果MyPackageFile1.javaMyPackageFile1.java在包com.example中声明,则存在三个问题:

  1. 您的源目录结构有误。应该是这样的:

    src
       com
          example
             MyPackageFile1.java
             MyPackageFile2.java
    
  2. 您使用了错误的类路径分隔符。由于您使用的是 Linux (基于路径名语法),类路径分隔符是 : 而不是 ;.

  3. 您使用的类路径 运行 代码错误。 java 命令行应该是这样的:

    java -cp vendor/something.jar:src:. Example
    

然而,这一切都非常 hacky。

  • 除非你的代码库需要模块化为多个代码树,否则你应该将你的Example源代码放入src目录;例如

    src
       Example.java
       com
          example
             MyPackageFile1.java
             MyPackageFile2.java
    
  • 将源代码和编译代码放在同一棵树中是个坏主意。一个更好的主意是使用 -d 选项;例如

    mkdir bin
    javac -cp bin:vendor/something.jar -d bin 
         src/Example.java 
         src/com/example/MyPackageFile1.java
         src/com/example/MyPackageFile12java
    
    java -cp bin:vendor/something.jar Example
    
  • 您应该使用某种构建工具...如果您希望您的构建具有一致性和可重现性。