如何处理具有大量 FOSS/COTS 的多个 jar 版本?
我们的 Java 产品使用了大量 FOSS/COTS 软件。我们的许多“外部”使用相同的 jar 产品,但版本不同。例如Ant 1.6.5和Ant 1.7.0;或 xerces 的多个版本。我担心的是,如果我们改变类路径的组合顺序,我们的应用程序的行为可能会发生变化,或更糟,甚至会发生史诗般的失败。我们使用 vbs 脚本为每个产品的类路径设置环境变量,然后使用引用这些环境变量的 Ant xml 文件。
那么,有几个问题:
- 当使用这么多不同的外部时,如何管理同一个 jar 的多个版本?当然,我不能只是找到所有独特的罐子并将它们放在一个大的类路径上 - 或者可以吗?
- 是否有更智能的方法将我们的构建依赖项(和类路径)放在一起?
一个积极的步骤是我计划使用通配符来获取所有罐子。但我最关心的实际上只是进口订单问题。
注意:不要射击信使。这个系统是几年前就开始实施的,早在我来到这里之前。我只是个清洁工
We have a Java product that uses a lot of FOSS/COTS software. A number of our "externals" use the same jar product, but a different version. For example, Ant 1.6.5 and Ant 1.7.0; or multiple versions of xerces. What's I'm concerned about is that the behavior of our application may change or worse, epic fail if we change the order in which the classpath is put together. We use vbs scripts to set environment variables for each product's classpath, and then Ant xml files which reference those environment variables.
So, a couple of questions:
- How do I manage multiple versions of the same jar when using so many different externals? Surely I can't just find all of the unique jars and put them on one big classpath - or can I?
- Is there a smarter way to put our build dependencies (and classpath) together?
One positive step is that I'm planning on using wildcards to grab all of the jars. But it's really just the import order problem that I'm mostly concerned about.
Note: Don't shoot the messenger. This system was put into place several years ago, long before I got here. I'm just the cleanup man.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
梅文。需要一段时间来弄清楚并设置它,但是一旦它工作起来就会非常神奇。
请参阅 http://maven.apache.org/download.html
Maven. Takes a while to figure it out and get it set up, but it is pretty magical once it is working.
See http://maven.apache.org/download.html
如果您必须将所有 jar 放在同一个类加载器中,那么您可以使用 maven 来确定依赖项集。这将选择依赖项集所需的每个库的最新版本。 (例如,将选择 Ant 1.7.0,而不是 1.6.5。)此方案效果很好 - 除非库不能向后兼容早期版本。因此,在更改依赖项时测试应用程序的相关功能/特性是个好主意。
另一种方法是在公共类加载器中加载接口,在自定义类加载器中加载实现+依赖项,这种方法只有在库可以分为接口和实现时才实用。这通过给它自己的类加载器来隔离每个依赖项。这本质上就是 OSGi 所做的事情。
If you have to put all the jars in the same class loader, then you can use maven to determine the set of dependencies. This will select the latest version of each library required by the set of dependencies. (E.g. Ant 1.7.0 will be selected, and not 1.6.5.) This scheme works well - unless a library is not backwards-compatible with an earlier version. Consequently, it's a good idea to test the relevant functions/features of your app when changing dependencies.
An alternative, which is only practical if the libraries can be split into interface and implementation, is to load the interfaces in a common class loader, and the implementations+dependencies in a custom class loader. This isolates each dependency by giving it it's own classloader. This is essentially what OSGi does.
您可以将 Ivy 添加到您的 ant 构建中以显式版本依赖项。在构建类路径时,我建议您尽量避免同一库的多个版本。我们遇到了一些非常烦人的行为,IDE 将使用传递依赖项构建类路径,但我们按字母顺序构建 unix 类路径,这导致根据运行代码的位置加载 Saxon/Xalan JavaMail/Genronimo-JavaMail 之一。
正如另一个答案中提到的,如果你有时间重新构建你的构建系统,你应该看看 Maven。
我非常喜欢这个谈话 John Smart 关于维护构建环境的文章
You could add Ivy into your ant build to explicitly version dependencies. When it comes to building a classpath, I'd suggest you strive for a situation where you don't have multiple versions of the same library. We had some very annoying behaviour where the IDE would build the classpath using transitive dependencies, but we build our unix classpath alphabetically which resulted in one of Saxon/Xalan JavaMail/Genronimo-JavaMail being loaded depending on where you ran the code.
As mentioned in the other answer, if you have time to re-work your build system you should look at maven.
I quite like this talk by John Smart on maintaining your build environment
我不确定使用 Maven 或 Ivy 的建议是否能解决真正的问题。他们可能会清理依赖关系的声明,但不会对冲突采取任何措施。如果您需要发布同一个库的两个不同版本(因为如果库不向后兼容,则使用最新版本不一定有效),您可以使用 jarjar 使用不同的包名称重新打包库,以便在必要时可以加载两个版本。
I'm not sure that the suggestions to use Maven or Ivy will solve the real problem. They may clean up declaration of dependencies but they won't do anything about conflicts. If you need to ship two different versions of the same library (because using the latest version will not necessarily work if the library is not backwards-compatible), you can use jarjar to repackage libraries with different package names so that both versions can be loaded if necessary.
这就是 OSGi 旨在解决的问题:在应用程序中拥有相同 jar 的多个独立版本。
This is what OSGi was designed to solve: Having multiple independent versions of the same jars in your application.