我正在编写一个多供应商 JMS 适配器,一些愚蠢的许可问题引发了对狡猾的类加载器解决方案/hack 的需求——它不会很漂亮,但我很想听听专家的一些巧妙想法类加载器黑客在那里......
架构很简单——适配器的所有代码都在系统类加载器中,并大量使用 Sun 的 J2EE javax.jms.jar 中的接口,然后根据类路径信息在子 URLClassLoaders 中加载各个 JMS 提供者对这些接口的实现从一些 XML 配置文件加载。
这一切都很好,直到我们意识到 Sun 的 J2EE JMS jar 受一个非常烦人的许可证管理,该许可证阻止我们重新分发它(即使它包含的只是行业标准接口!)所以我们不能把它放在系统类路径中连同我们的开箱即用代码。但是,如果客户被迫从 Sun 网站查找并下载 jar,然后将其复制到我们安装中的正确位置以使其正常工作,最终用户体验将非常糟糕。考虑到我们正在加载的 JMS 提供程序实现必然已经在我们自己的 JVM 中加载了所有这些接口,因此对客户施加这样的刺激似乎是一种耻辱——唯一的问题是它们位于特定于提供程序的子类加载器中意味着他们'
所以我很想听听任何聪明的想法来解决这个问题(如果可能的话!)。
例如,我想知道尝试在自定义的 urlclassloader 子类中加载我们的主类,而不是使用系统类加载器(尽管这将是相当痛苦的,因为我们必须重现现有 MANIFEST.MF 类路径引用的效果)并提供该类加载器对其中一个子类加载器的引用(一旦我们解析了我们的 XML 配置),因此它可以(仅)从子类加载“javax.jms.*”接口(颠覆正常的父优先策略,并忽略供应商- 同一个 jar 中的特定类,不得在父级中加载)。我想知道这是否可行,是否有人有任何指示。一世' 我注意到主 CL 中的一些适配器类正确加载,尽管有引用缺少的 JMS 接口的方法(但在调用这些方法时显然会失败) - 我是否正确地认为,如果可以提供包含这些类的 CL在调用此类方法时(但在加载类之后)访问 JMS 接口,那么它会起作用吗?(或者已经太晚了……)
(仅供参考,我已经发现了两个相关的 stackoverflow 帖子,它们提供了一些有用的上下文,但不能完全帮助解决这个特定的问题:How do you change the CLASSPATH within Java?和How do I create a parent-last / child-first ClassLoader in Java ,或如何覆盖已在父 CL 中加载的旧 Xerces 版本?)
非常感谢你帮我解决这个问题!:)