I have a tomcat application starting with a set of jars in the classpath.
Assume ClassA, ClassB, ClassC are used after startup. So, these classes are loaded into the JVM. All these classes are loaded from different jars from the same folder.
Now, I can use ClassB.method() from ClassA. It works perfectly.
Now, I add more jars from a different folder to the classpath at runtime. In these jars also, there is ClassB. The ClassB loaded during startup and this are different version.
Now, when I use ClassB.method() from ClassA I get LinkageError.
I get the error even if both the jars are same version.
When the new jar is added to the JVM at runtime, what happens to the old loaded class? Does ClassA store which version of ClassB it first loaded? If it doesn't how does JVM know there is a signature difference and throw the error?
Code used to add jars at runtime
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());
}
LinkageError
java.lang.LinkageError: loader constraint violation: when resolving method "org.apache.http.client.methods.HttpPost.setEntity(Lorg/apache/http/HttpEntity;)V" the class loader (instance of java/net/URLClassLoader) of the current class, com/application/rest/tokens/TokenHandler, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method's defining class, org/apache/http/client/methods/HttpEntityEnclosingRequestBase, have different Class objects for the type org/apache/http/HttpEntity used in the signature