我将app.jar作为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
app.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)
libthrift-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
存在且必须在运行时可访问。但不要。为什么这样?
答案 0 :(得分:2)
第一:默认情况下,如果你没有使用任何特殊的工具/框架(比如spring-boot),你就不能在jar中使用jar。
第二:你的清单文件中的条目(如Class-Path:lib / libthrift-0.9.3.jar等)不是引用jar中的jar,而是引用jar附近文件系统中的jar。即,使用java -jar app.jar
运行应用程序的文件结构应为:
./
/libs --> all 3-d party jars here
app.jar
如果你想把所有的变种放在一个罐子里,其中一个变种就是使用所谓的“超级罐子”。 - 在这种情况下,所有三维派对类都从他们的罐子中提取出来,并与你自己的类一起打包在一个罐子里。
例如,可以使用maven build Shade Plugin。
答案 1 :(得分:1)
在打包app.jar时,只需将libthrift-0.9.3.jar等外部/第三方库放在app.jar旁边名为“lib”的文件夹/目录中。让你Manifest条目保持不变。执行时,使用java -cp。 -jar app.jar。另外,就像inigo说的那样,只需使用像eclipse这样的工具并将所有库包装在jar中。另一种选择是简单地从外部jar中提取所有类文件,例如thrift,并将它们打包到app.jar中。在这种情况下,您可以按照自己的意愿运行它。