部署概念:打包 JAR 依赖项、何时以及何时打包为什么
因此,我对 Java EE 比较陌生,并且很难理解 Java 部署文件何时、何地以及为何与其依赖项一起打包。
假设我将项目构建到 myapp.jar 中,它依赖于 fizz.jar、buzz.jar 和 JODA (joda-time-2.0.jar
)。
我听说默认的类加载器不会将 jar 打包到其他 jar 中,因此我必须假设如果我从 Ant 调用 jar 任务,那么默认的类加载器将被调用并且 myapp.jar 将在创建时不包含这 3 个依赖项。
这是因为我们的想法是在容器或其他系统中部署main
-less jar,以便在运行时提供其需求吗?如果没有,那么 myapp.jar 如何正确运行?
可执行 jar 怎么样?为了满足这一要求,这些必须与无main
的jar不同,因为它们是独立的单元,对吧?这意味着他们需要将所有依赖项一起打包,对吧?
最后但并非最不重要的一点是,那些依赖于 jar 的 jar 又依赖于 jar 的 jar 又如何……等等。 (即巨大的依赖图)?
我想所有这些问题都可以总结如下:
- 不可执行的 jar 背后的想法是否是,它将以这样一种方式运行,即它知道在运行时要查找其依赖项的类路径? (因此不需要与其依赖项一起打包)?
- 可执行 jar 背后的想法是它是一个独立的单元并且应该与其依赖项一起打包吗?
- 如果我对上面问题#1 的断言是正确的,那么这样的类路径配置是如何发生的?这些设置是否存储在 jar 内(例如在清单中)?否则,JRE 如何知道在运行时在哪里搜索特定的 jar 依赖项?
这些问题的答案实际上将澄清我对 Java 基础知识的很多困惑,因此这里的任何输入/帮助都将受到极大的赞赏!谢谢
So I'm relatively new to Java EE and I am having a tough time understanding when, where and why Java deployment files are packaged with their dependencies.
Say I build my project into myapp.jar, and it depends on fizz.jar, buzz.jar and JODA (joda-time-2.0.jar
).
I've heard that the default classloader doesn't package jars inside of other jars, so I have to assume that if I called a jar task from Ant, then the default classloader would get invoked and myapp.jar would be created without those 3 dependencies in it.
Is this because the mentality is to deploy main
-less jars in containers or other systems that will provide its requirements at runtime? If not, then how does myapp.jar ever run correctly?
What about executable jars? To met, these must be different than main
-less jars, because they are meant to be standalone units, right? That means they would need all of their dependencies packaged with them, right?
Last but not least, what about jars that depend on jars that depend on jars...etc. (i.e., dependencygraphs that are huge)?
I guess all of these questions can be summed up as follows:
- Is the idea behind a non-executable jar that it will be ran in such a way that it will know what classpath(s) to look on for its dependencies at runtime? (And thus doesn't need to be packaged with its dependencies)?
- Is the idea behind an executable jar that it is a standalone unit and should be pacakged with its dependencies?
- If my assertion to Question #1 above is correct, how does such classpath configuration take place? Are these settings that are stored inside the jar (such as in the manifest)? Else, how would a JRE know where to search for a particular jars dependencies at runtime?
Answers to these questions will actually clarify quite a lot of hangups I have with Java fundamentals, and so any input/help here will be appreciated enormously! Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Jars 不知道其他 jars(除非有 Maven 之类的工具辅助)。 jar 的相互依赖性完全由类加载器解决。我强烈建议一些关于类加载器的想法 。
为了解决您的问题,
不可执行的 jar 背后的想法是,它将以这样一种方式运行,即它知道在运行时要查找其依赖项的类路径? (因此不需要与其依赖项一起打包)?
可执行 jar 背后的想法是它是一个独立的单元并且应该与其依赖项一起打包吗?
如果我对上面问题 #1 的断言是正确的,那么这样的类路径配置是如何发生的?这些设置是否存储在 jar 内(例如在清单中)?否则,JRE 如何知道在运行时在哪里搜索特定的 jar 依赖项?
简而言之,类加载器正在拉动所有线程。它在标准位置查找所有依赖的 jar 包。 此链接很好地描述了独立应用程序和已部署应用程序中的类加载器(在某些情况下)容器)有效。
Jars do not know about other jars (unless assisted by some tools like Maven). The inter dependency of the jars is purely resolved by the Classloaders. I strongly recommend to have some idea about classloaders.
To address your questions,
Is the idea behind a non-executable jar that it will be ran in such a way that it will know what classpath(s) to look on for its dependencies at runtime? (And thus doesn't need to be packaged with its dependencies)?
Is the idea behind an executable jar that it is a standalone unit and should be packaged with its dependencies?
If my assertion to Question #1 above is correct, how does such classpath configuration take place? Are these settings that are stored inside the jar (such as in the manifest)? Else, how would a JRE know where to search for a particular jars dependencies at runtime?
In a nutshell, it's the classloader which is pulling all the threads. There is standard places where it looks for all the dependent jars. This link nicely describes how the classloaders in standalone application and in a deployed (in some container) works.
JAR 文件是一种将复杂的 java 应用程序打包在一起的方法。 Jar 应用程序很容易在不同的机器和操作系统之间移动。
我认为使用 Jars 的正确方法不是将所有内容(每个依赖项)放入一个 jar 中。
例如,如果您的应用程序使用 jar libryra(例如 jdbc)来访问数据库,则不应将 jdbc jar 放入您的 jar 中。
您最好仅使用 .class 文件构建一个 jar 文件。
当然,您的代码需要 jdbc jar 才能正常工作。这里解释一下虚拟机如何搜索外部类:
- 它首先在包含J2SE标准类的目录中搜索(路径取决于你的安装)
- 它在类路径(一个类路径)指定的目录中搜索是环境变量或 java 命令的选项)
例如:
java -jar -c /your/path/ yourApp.jar
将运行您的应用程序,并将搜索您的应用程序在目录 /your/path/ 中引用的类所以如果你有外部罐子你可以将它们放在该目录中。
有关详细文档: http://download.oracle.com/javase/tutorial /deployment/jar/index.html
JAR files are a way to package togher complex java application. Jar application are easy to move between diffrent machines and operating system.
I think the right way to use Jars is not tu put everything (every dependencies) into a single jar.
For example if your application uses a jar libryra (for example jdbc) to access a database you should not put the jdbc jar into your jar.
You had better to build a jar file with only your .class file.
Of course your code needs the jdbc jar to work properly. Here comes to explain how the virtual machine searches for extarnal classes:
-it first searches in the directories that contain the classes that come standard with J2SE (the path depends on your installation)
-it searches in the directories specified by the classpath (a classpath is either an environment variable or an option of the java command)
for example:
java -jar -c /your/path/ yourApp.jar
will run your application and will search th classes your application refers to in the directory /your/path/ so if you have external jars you can put them in that directory.
For detailed documentation: http://download.oracle.com/javase/tutorial/deployment/jar/index.html