在我的Java项目中,我使用了两个不同的框架(比如A.jar和B.jar),它们都需要一个通用框架(比如说Log4j.jar),但需要两个不同的版本。如果框架A需要Log4J v1.1并且B需要Log4j v1.2,Java如何处理?它会导致某种冲突/错误,还是会以某种方式(如何?)解决?
如果它不会导致冲突/错误(我的项目可以编译和运行) - 我可以在这个项目中自己使用任何版本的Log4j吗?或者我是否被迫选择较低/较高版本的Log4j?
更新: 更具体...... 如果在v1.2中更改了Log4j API的某些部分(假设一个方法doIt()签名已更改)并且A和B都调用了doIt,该怎么办?会发生什么?我的项目会运行吗?首次使用doIt会崩溃吗?我必须在classpath-v1.2或两者上放置什么版本的Log4j?
答案 0 :(得分:11)
在平面类加载方案中,没有库版本控制支持。您需要使用最新版本的库并从类路径中删除其他版本。
某些框架(如OSGi)提供了处理这些案例的机制,但您不清楚是否依赖于插件框架。
编辑:
如果v4.2中的Log4j API的某些部分发生了变化(假设单个方法
doIt()
签名已更改),并且A和B都调用doIt
,该怎么办?会发生什么?我的项目会运行吗?首次使用doIt
时会崩溃吗?
依赖于不存在的签名的呼叫可能会导致NoSuchMethodError
。在调用该方法之前,这可能不会发生。如果其他机制依赖于签名(例如类继承),则可能发生其他错误。
我必须在classpath-v1.2或两者上放置什么版本的Log4j?
在类路径上创建两个版本的库只会导致一组类被随机加载。行为将是未定义的,但可能会导致各种令人不快的错误和异常。
答案 1 :(得分:3)
如果您幸运地挑选第三方罐子的一个版本就可以了。最后,需要一个能够理解并允许所有组件版本化共存的容器,例如OSGI。
答案 2 :(得分:3)
Java 本地支持管理同一段代码的多个版本,也就是说,您只能在同一个JVM中使用最多一个版本(使用默认的类加载器) 。但是,结帐问题1705720,其中有几个答案指出了实现这一目标的可能方法(OSGi或自定义类加载器)。
但我怀疑这是值得的,因为您的代码不需要多个log4j版本。在你的情况下,我建议首先使用较新的log4j版本(v1.2),并验证它是否会导致框架A的任何问题。如果它确实导致冲突,那么回退到log4j v1.1和再次验证。如果你真的没有运气,那么你需要弄清楚......
更新:对于您的具体描述,无法使用log4j v1.1或v1.2,因为框架A和B都需要不同的签名。您必须滚动自己的任何log4j或框架A或B的版本。
答案 3 :(得分:0)
虽然不推荐,但您可以同时使用这两个版本。将每个版本放在只有该框架可以看到的地方。
最佳解决方案是获取A和B的最新版本,其中两者都使用最后的公共库