我知道要组合几个jar并创建一个可执行jar,如果我不想解压缩依赖的jar,我需要使用像OneJar这样的工具。 OneJar有自己的自定义类加载器,可以在相关的jar中找到所需的类并加载它们。
我的问题是:为什么默认的类加载器无法从附加的jar中加载类。是因为安全吗? 我很感激清楚地解释了在创建一个包含其他依赖jar的单个可执行jar时需要自定义类加载器的原因(不解包它们)。 谢谢,
答案 0 :(得分:2)
技术原因是jar:
的uri规范不支持嵌套。
您可以编写一个满足此需求的URI处理程序,但是当您在每个jar文件中嵌套时性能将开始下降。
使用单个jar文件,随机访问是可能的,因为索引提供了文件系统偏移量,您可以查找每个偏移量并只读取您想要的文件
使用嵌套的jar,您可以寻找内部jar,但是要从该jar中取出一个文件,您必须先从内部解压缩内部jar,然后再进行搜索。
如果您不想将jar文件解压缩到临时目录并从生成的类路径构建自己的类加载器,我会查看OSGi或Maven Shade插件提供的解决方案
答案 1 :(得分:1)
除了其他答案(Stephen迄今为止更准确的答案)之外,还要考虑JVM没有抢先探索可用的类路径条目,因此为了找到类 com.foo.Bar < / em>它将在类路径中的列出条目中查看类似 com / foo / Bar.class 的路径。如果此路径可能位于嵌套jar中(它本身不在类路径声明中列出),为了找到所述路径,类加载器应首先探索所有嵌套jar(在进程中解压缩)以便进行相应的查找
答案 2 :(得分:0)
我怀疑这个决定是出于安全性的考虑:如果通过嵌套使得任何东西变得更安全或更不安全,那将是令人惊讶的。实际上,能够在我的超级JAR中签署所有JAR作为一个整体并且在验证我的JAR时检查它们的完整性可能是非常好的。
我认为主要原因是性能和简洁性。如果JAR可以嵌套,那么这些问题的答案应该是什么:
将JAR看作是一个共享库似乎是最直接的:它是一个很好的,打包的,索引的,签名的,扁平的,随时可用的链接包。值得注意的是Unix .so和Windows .dll也不允许嵌套,并且出于同样的原因我怀疑。
旁注:通常不需要创建“uberjar”:通常可以使用主JAR清单中的Class-Path
字段来允许它引入外部库。
答案 3 :(得分:0)
您可以将应用程序所需的所有jar放在app文件夹(例如lib)中并使用
java -cp lib/*.jar ...
或枚举主jar的清单Class-Path属性中的所有jar。