针对非 OSGi 开发人员的 JAR Hell Hacks

发布于 2024-12-05 22:36:24 字数 1001 浏览 2 评论 0原文

编辑:在回顾了该剧之后,我在下面使用的示例有点具有误导性。我正在寻找这样的情况:我有两个第三方 jar(不是我可以访问源代码的自制 jar),它们都依赖于同一 jar 的不同版本。


原文: 因此,我最近熟悉了 OSGi 是什么,以及它解决的核心问题(“JAR Hell”)。而且,尽管我对它很感兴趣(并计划在未来迁移到某个地方),但我只是没有能力开始学习如何将我的项目带到它上面。

所以,我现在感叹:如果 JAR 地狱发生在我身上,我该如何在没有 OSGi 的情况下解决这个问题?

显然,解决方案几乎必须涉及编写我自己的ClassLoader,但我很难想象这将如何表现出来,更重要的是,这将如何表现出来解决问题。我做了一些研究,一致认为你必须为你生成的每个 JAR 编写自己的类加载器,但由于我已经很难透过树木看到森林,所以我并没有理解这个说法。

有人可以提供一个具体的例子来说明如何编写我自己的类加载器来在这个巨大的伤口上贴上创可贴(我知道,我知道,唯一真正的解决方案是 OSGi)?

假设我编写了一个名为 SuperJar-1.0.jar 的新 JAR,它可以完成各种令人惊奇的事情。假设我的 SuperJar-1.0.jar 还有另外两个依赖项:Fizz-1.0.jarBuzz-1.0.jarFizzBuzz jar 都依赖于 log4j,除了 Fizz-1.0.jar 依赖于 log4j- 1.2.15.jar,而 Buzz-1.0.jar 依赖于 log4j-1.2.16.jar。同一个罐子的两个不同版本。

基于类加载器的解决方案如何解决这个问题(简而言之)?

Edit: After reviewing the play, the example I used below is a tad misleading. I am looking for the case where I have two 3rd party jars (not homegrown jars where I have access to the source code) that both depend on different versions of the same jar.


Original:
So I've recently familiarized myself with what OSGi is, and what ("JAR Hell") problems it addresses at its core. And, as intrigued as I am with it (and plan on migrating somewhere down the road), I just don't have it in me to begin learning what it will take to bring my projects over to it.

So, I'm now lamenting: if JAR hell happens to me, how do I solve this sans OSGi?

Obviously, the solution would almost have to involve writing my own ClassLoader, but I'm having a tough time visualizing how that would manifest itself, and more importantly, how that would solve the problem. I did some research and the consensus was that you have to write your own ClassLoader for every JAR you produce, but since I'm already having a tough time seeing that forest through the trees, that statement isn't sinking in with me.

Can someone provide a concrete example of how writing my own ClassLoader would put a band-aid on this gaping wound (I know, I know, the only real solution is OSGi)?

Say I write a new JAR called SuperJar-1.0.jar that does all sorts of amazing stuff. Say my SuperJar-1.0.jar has two other dependencies, Fizz-1.0.jar and Buzz-1.0.jar. Both Fizz and Buzz jars depend on log4j, except Fizz-1.0.jar depends on log4j-1.2.15.jar, whereas Buzz-1.0.jar depends on log4j-1.2.16.jar. Two different versions of the same jar.

How could a ClassLoader-based solution resolve this (in a nutshell)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陈甜 2024-12-12 22:36:25

如果您从“我正在构建一个应用程序,如何避免这个问题”而不是“我需要这个特定的解决方案”的角度来问这个问题,我强烈更喜欢 Maven 方法 - 即,只解决任何给定依赖项的单一版本。以log4j 1.2.15为例-> 1.2.16,这会正常工作 - 您只能包含 1.2.16。由于旧版本是 API 兼容的(它只是一个补丁版本),因此 Fizz 1.0 很可能不会注意到它正在使用比预期更新的版本。

您会发现这样做可能会更容易调试问题(没有什么比让类或静态字段的多个版本浮动更让我困惑的了!谁知道您正在处理哪一个! )并且不需要任何聪明的类加载器技巧。

If you're asking this question from an "I'm building an app, how do I avoid this" problem rather than a "I need this particular solution" angle, I would strongly prefer the Maven approach - namely, to only resolve a single version of any given dependency. In the case of log4j 1.2.15 -> 1.2.16, this will work fine - you can include only 1.2.16. Since the older version is API compatible (it's just a patch release) it's extremely likely that Fizz 1.0 won't even notice that it's using a newer version than it expected.

You'll find that doing this will probably be way easier to debug issues with (nothing confuses me like having multiple versions of even classes or static fields floating around! Who knows which one you're dealing with!) and doesn't need any clever class loader hacks.

静待花开 2024-12-12 22:36:25

但是,这正是所有应用程序服务器都必须处理的问题。假设您的 Fizz 和 Buzz 是 Web 应用程序 (WAR),而 Super-Jar 是您的应用程序服务器。 Super-Jar 将为每个 Web 应用程序安排一个类加载器,“打破”正常的委托模型,即在查找层次结构之前它将在本地(向下)查找。去阅读任何应用程序服务器的文档。例如 http://download.oracle.com /docs/cd/E19798-01/821-1752/beade/index.html

But, this is exactly what all the appservers out there have to deal with. Pretend that your Fizz and Buzz are web applications (WARs), and Super-Jar is you appserver. Super-Jar will arrange a class loader for each web app that "breaks" the normal delegation model, i.e. it will look locally (down) before looking up the hierarchy. Go read about it in any of the appservers's documentation. For example http://download.oracle.com/docs/cd/E19798-01/821-1752/beade/index.html.

岁月静好 2024-12-12 22:36:25

使用log4j-1.2.16。它仅包含 1.2.15 的错误修复。

如果 Fizz 破坏了 1.2.16,请分叉并修补它,然后将这些修补程序提交给 Fizz 的作者。

使用特殊委托逻辑创建自定义类加载器的替代方案非常复杂,并且可能会导致许多问题。我不明白为什么你会想要这样做而不是仅仅使用 OSGi。您是否考虑过创建一个嵌入式 OSGi 框架,这样您就不必转换整个应用程序?

Use log4j-1.2.16. It only contains bugfixes wrt 1.2.15.

If Fizz breaks with 1.2.16, fork and patch it, then submit those patches back to the author of Fizz.

The alternative of creating custom classloaders with special delegation logic is very complex and likely to cause you many problems. I don't see why you would want to do this rather than just use OSGi. Have you considered creating an embedded OSGi framework, so you don't have to convert your whole application?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文