我有一个从类路径中的一组 jar 开始的 tomcat 应用程序。
假设启动后使用ClassA、ClassB、ClassC。因此,这些类被加载到 JVM 中。所有这些类都是从同一文件夹中的不同 jar 加载的。
现在,我可以ClassB.method()
从 ClassA 使用。它完美地工作。
现在,我在运行时将来自不同文件夹的更多 jar 添加到类路径中。在这些罐子里,还有 ClassB。ClassB 在启动期间加载,这是不同的版本。
现在,当我ClassB.method()
从 ClassA 使用时,我得到了 LinkageError。
即使两个 jar 版本相同,我也会收到错误消息。
当新的 jar 在运行时添加到 JVM 时,旧加载的类会发生什么?ClassA 是否存储它首先加载的 ClassB 版本?如果没有,JVM如何知道存在签名差异并抛出错误?
用于在运行时添加 jar 的代码
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); //NO I18N
method.setAccessible(true);
File jarFolder = new File("<path-to-new-jar-folder>");
Collection<File> jarFiles = FileUtils.listFiles(jarFolder, new String[]{ "jar"}, true); //NO I18N
for(File jarFile : jarFiles)
{
method.invoke(urlClassLoader, jarFile.toURI().toURL());
}
联动错误
java.lang.LinkageError: 加载器约束违规:当解析方法“org.apache.http.client.methods.HttpPost.setEntity(Lorg/apache/http/HttpEntity;)V”类加载器(java/net/URLClassLoader 的实例) 的当前类 com/application/rest/tokens/TokenHandler 和方法定义类 org/apache/http/client/methods/HttpEntityEnclosureRequestBase 的类加载器(sun/misc/Launcher$AppClassLoader 的实例)签名中使用的 org/apache/http/HttpEntity 类型的不同 Class 对象