代码之家  ›  专栏  ›  技术社区  ›  jonua

应用程序中没有ClassDefFoundError,类路径是正确的(乍一看)。为什么?

  •  0
  • jonua  · 技术社区  · 8 年前

    我运行我的应用程序。震击器组件 java -jar app.jar 并查看下一个错误:

    Error: A JNI error has occurred, please check your installation and try again
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/thrift/transport/TTransportException
    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: org.apache.thrift.transport.TTransportException
    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 结构:

        .
        ├── lib
        │   ├── ... (some *.jar files)
        │   ├── libthrift-0.9.3.jar
        │   └── ... (some *.jar files)
        ├── META-INF
        │   ├── MANIFEST.MF
        │   └── maven
        │       └── groupId-name
        │           └── artifactId-name
        │               ├── pom.properties
        │               └── pom.xml
        └── ... *.class files of app
    

    在里面 META-INF/MANIFEST.MF 声明为 classpath 作为:

    Class-Path: lib/libthrift-0.9.3.jar lib/...(other *.jar's from lib/ folder)
    

    诽谤-0.9.3.jar 结构:

        .
        ├── META-INF
        │   ├── LICENSE.txt
        │   ├── MANIFEST.MF
        │   └── NOTICE.txt
        └── org
            └── apache
                └── ... some packages with files
                    ├── transport
                    │   ├── ... some files
                    │   ├── TTransportException.class
                    │   └── ...
                    └── ...
    

    就像你看到的,同学们 org.apache.transport.TTransportException 存在,并且必须在运行时可以访问。但不要这样。为什么如此?

    2 回复  |  直到 8 年前
        1
  •  2
  •   inigo skimmer    8 年前

    第一:默认情况下,在java中,如果您没有使用任何特殊工具/框架(如springboot),那么jar中就不能有jar。

    第二:Manifest文件中的条目(如类路径:lib/librict-0.9.3.jar等)引用的不是jar中的jar,而是jar附近文件系统中的jars。一、 e用于运行应用程序的文件结构 java -jar app.jar 应该是:

    ./
     /libs --> all 3-d party jars here
     app.jar
    

    如果你想把所有的东西都放在一个jar中,其中一个变体就是使用所谓的“uber jar”——在这种情况下,所有的3d party类都是从它们的jar中提取出来的,并与你自己的类一起打包在一个jar中。

    例如,maven build Shade Plugin 可以使用。

        2
  •  1
  •   Snigdhadeb Mukherjee    8 年前

    打包应用程序时。jar,只需将外部/第三方库(如librict-0.9.3.jar)放在app.jar旁边名为“lib”的文件夹/目录中。让您的清单条目保持不变。执行时,使用java-cp.-jar app.jar。否则,正如inigo所说,只需使用eclipse之类的工具,并将所有库打包到jar中即可。另一种选择是简单地从外部jar(如redict)中提取所有类文件,并将它们打包到app.jar中。在这种情况下,您可以简单地运行它。