java 是否可以将所有 jar 依赖项打包在一个大 jar 中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1059851/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to package all the jar dependencies in one big jar?
提问by Geo
I know this isn't "best practice", but can I include all of the dependencies in one big jar?
我知道这不是“最佳实践”,但是我可以将所有依赖项都包含在一个大罐子中吗?
采纳答案by skaffman
回答by abb
My feeling is that calling One-Jar's performance awful and poor is unjust. For moderately sized application one can expect startup will take a couple of seconds longer (which does not affect JVM splash screen though). Memory overhead of tens of megabytes is negligible for most environments, except perhaps embedded systems. Also, One-Jar is capable of automatically extracting some files to the file system, which saves the need to develop an installer in my case.
我的感觉是,称 One-Jar 的表现糟糕而糟糕是不公正的。对于中等大小的应用程序,可以预期启动时间会延长几秒钟(尽管这不会影响 JVM 启动画面)。对于大多数环境来说,数十兆字节的内存开销可以忽略不计,也许嵌入式系统除外。此外,One-Jar 能够自动将一些文件提取到文件系统,这在我的情况下无需开发安装程序。
Below is an attempt to quantify the performance impact introduced by One-Jar to my application. It is Swing-based GUI application, consists of 352 classes obfuscated with ProGuard 4.5b2. One-Jar 0.96 is used to bundle resulting classes with 12MB worth of libraries (ODFDOM, Saxon HE, Xerces, Jaxen, VLDocking, Apache Commons, etc). I have compared performance of the obfuscated jar with the same jar processed by One-Jar.
下面是量化 One-Jar 对我的应用程序引入的性能影响的尝试。它是基于 Swing 的 GUI 应用程序,由使用 ProGuard 4.5b2 混淆的 352 个类组成。One-Jar 0.96 用于将生成的类与价值 12MB 的库(ODFDOM、Saxon HE、Xerces、Jaxen、VLDocking、Apache Commons 等)捆绑在一起。我将混淆 jar 的性能与 One-Jar 处理的同一个 jar 进行了比较。
- From JVM start to the start of of main() method: 0.5s without One-Jar and 1.7s with One-Jar. From JVM start to the appearance of application window on the screen: 2.3s without One-Jar and 3.4s with One-Jar. So One-Jar adds 1.1s to startup time.
- One-Jar will not increase the delay between JVM start and splash image appearing on the screen (if implemented via jar manifest), so the startup time increase is not too annoying for interactive applications.
- We are talking about a class loader, so there should be no impact on code execution speed, unless you are extensively using dynamic class loading.
- Looking at JVM statistics (via jconsole) shows that One-Jar'red version takes more heap memory. For my application the overhead is in the order of tens of MBs. I saw figures like 16MB vs 40MB, 306MB vs 346MB, 131MB vs 138MB, depending on now much user data the application is handling and now long time ago garbage collector has been executed.
- 从JVM启动到main()方法启动:0.5s没有One-Jar,1.7s有One-Jar。从JVM启动到应用程序窗口出现在屏幕上:没有One-Jar需要2.3s,有One-Jar需要3.4s。所以 One-Jar 将启动时间增加了 1.1 秒。
- One-Jar 不会增加 JVM 启动和屏幕上出现的启动图像之间的延迟(如果通过 jar 清单实现),因此启动时间的增加对于交互式应用程序来说不会太烦人。
- 我们谈论的是类加载器,因此应该不会对代码执行速度产生影响,除非您广泛使用动态类加载。
- 查看 JVM 统计数据(通过 jconsole)表明 One-Jar'red 版本需要更多的堆内存。对于我的应用程序,开销约为数十 MB。我看到了诸如 16MB 与 40MB、306MB 与 346MB、131MB 与 138MB 之类的数字,这取决于应用程序现在处理的大量用户数据以及很久以前垃圾收集器已被执行的情况。
The above timing was obtained by taking a timestamp just before starting JVM from Linux shell, in beginning of main() method, and in windowOpened() event handler of my application window. The measurements were taken on a not particularly fast D820 laptop, with dual core 1GHz CPU and 2G or RAM running Ubuntu 8.04.
上述时间是通过在从 Linux shell 启动 JVM 之前、在 main() 方法的开头以及在我的应用程序窗口的 windowOpened() 事件处理程序中获取时间戳来获得的。测量是在一台速度不是特别快的 D820 笔记本电脑上进行的,双核 1GHz CPU 和 2G 或 RAM 运行 Ubuntu 8.04。
Hope it helps.
希望能帮助到你。
回答by dfa
I used maven assembly pluginwith jar-with-dependenciesdescriptor
我使用带有jar-with-dependencies描述符的maven 程序集插件
回答by Vladimir
Using the good old Ant: just use zipgroupfilesetwith the Ant Zip task
使用旧的 Ant:只需zipgroupfileset与 Ant Zip 任务一起使用
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
This will flatten all included jar libraries' content.
这将展平所有包含的 jar 库的内容。
回答by simontuffs
One-JAR loads all the dependency jars into memory on startup. This may sound horribly inefficient, but nobody has complained to me about it since it was released in 2004. The likely effect of pre-loading is an overall speed up of classloading for the application, since the classloader does not have to repeatedly scan the classpath for resources and classes as the application runs: everything is hashmapped.
One-JAR 在启动时将所有依赖项 jar 加载到内存中。这听起来可能非常低效,但自从它于 2004 年发布以来,没有人向我抱怨过它。预加载的可能效果是应用程序类加载的整体加速,因为类加载器不必重复扫描类路径对于应用程序运行时的资源和类:一切都经过哈希映射。
It's pretty simple to build a lazy loader which would load on-demand: but I'm of the school that says "build-it, measure-it, improve-it if necessary" and so far there has been no need to improve it.
构建一个按需加载的惰性加载器非常简单:但我所在的学校说“构建它,测量它,必要时改进它”,到目前为止还没有必要改进它.
I will keep this in mind for future releases (or if someone else wants to tackle it, that would be great too, since without a very large application to measure against, it's hard to know if changes are improvements).
我会在未来的版本中牢记这一点(或者如果其他人想要解决它,那也很好,因为没有一个非常大的应用程序来衡量,很难知道更改是否是改进)。
回答by Dave Webb
If you want to do this there is a tool called Jar Jar Linkswhich will do this for you. Never used it but it is hard to forget the name.
如果您想这样做,有一个名为Jar Jar Links的工具可以为您执行此操作。从未使用过它,但很难忘记它的名字。
回答by Brian Sweeney
Eclipse 3.4 and up allows you to do this. Right click your project, select Extract, and navigate to the Runnable Jar option. Select Next. Choose the appropriate settings and your off and running. Also I seem to recall that this functionality is achieved using the same or similar libraries that FatJar (mentioned above) uses.
Eclipse 3.4 及更高版本允许您执行此操作。右键单击您的项目,选择 Extract,然后导航到 Runnable Jar 选项。选择下一步。选择适当的设置和您的关机和运行。我似乎还记得这个功能是使用 FatJar(上面提到的)使用的相同或相似的库来实现的。
回答by Lawrence Dol
回答by Lawrence Dol
回答by lavinio
Often you can, but sometimes there are unusual legalor technicalreasons not to.
通常你可以,但有时有不寻常的法律或技术原因不这样做。
Legal:For example, we discovered that at the time we wanted to, we could not bundle the JavaMail jar files together into one big package with the rest of our app, but the license agreement said we had to keep them separate.
Technical:Another problem might be custom class loaders look for specific resources or classes inside of specific jar files. This often happens in the context of containers for application servers or ESBs.
法律:例如,我们发现在我们想要的时候,我们无法将 JavaMail jar 文件与我们应用程序的其余部分捆绑到一个大包中,但是许可协议规定我们必须将它们分开。
技术:另一个问题可能是自定义类加载器在特定 jar 文件中查找特定资源或类。这通常发生在应用程序服务器或 ESB 的容器环境中。
How: To do it, just unjar everything into one directory, and then rebuild a jar from there. You might have to tweak some settings in the META-INF folder to remove the requests to load the additional jars, and to handle the case where different jars each have a default class to run. There are some third-party utilities which might help, but unless you know whatthey are doing, you'd want to be careful.
如何:要做到这一点,只需将所有内容解压缩到一个目录中,然后从那里重建一个 jar。您可能需要调整 META-INF 文件夹中的一些设置以删除加载其他 jar 的请求,并处理不同的 jar 每个都有一个默认类要运行的情况。有一些第三方实用程序可能有帮助,但除非你知道什么,他们在做什么,你要小心。

