Classloading Using Different Versions Of The Same Class : java.lang.LinkageError : attempted duplicate class definition for name

僤鯓⒐⒋嵵緔 提交于 2019-12-05 17:05:38
Francisco Hernandez

I think the problem would become from the parent ClassLoader you are using. You are not overloading loadClass method, so you are delegating in parent class, concretely in ClassLoader.getSystemClassLoader().

As javadoc says at https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#getSystemClassLoader()

This method is first invoked early in the runtime's startup sequence, at which point it creates the system class loader and sets it as the context class loader of the invoking Thread.

You want to load the changed classes but you are delegating to the Thread ClassLoader the operation, is a bit confusing.

You can do something like this, using your own Class ClassLoader

package a;

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;

public class ReloadTest {

    public static void main(String[] args) throws ClassNotFoundException, IOException {

        final Class<?> clazz = ReloadTest.class;

        System.out.println("Class: " +  clazz.hashCode());

        final URL[] urls = new URL[1];

        urls[0] =  clazz.getProtectionDomain().getCodeSource().getLocation();
        final ClassLoader delegateParent = clazz.getClassLoader().getParent();

        try (final URLClassLoader cl = new URLClassLoader(urls, delegateParent)) {

            final Class<?> reloadedClazz = cl.loadClass(clazz.getName());
            System.out.println("Class reloaded: " + reloadedClazz.hashCode());
            System.out.println("Are the same: " + (clazz != reloadedClazz) );
        }
    }
}

Hope helps!

P.D: This link is related to the same problems, may it help too Reload used classes at runtime Java

How can I solve this problem? Is there any way to unload a class, or else, anyway to reload a class with same name?

There is no way to force1 a class to unload. And unless the old class is unloaded, there is no way to load a new version of a class into the same classloader. (That is because the true identity of a class is a tuple comprising the fully qualified name of the class and the class loader identity.)

The solution is to load the new version of the class in a new classloader.

It is not clear if this will be practical for you, but unfortunately it is the only option available. The JVM does the "duplicate class definition" checks in a way that you can't subvert it. The check has security and JVM stability implications.


1 - A class that is not referenced by any reachable object will eventually be unloaded by the GC (modulo JVM command line options, versions, etc). However, it can be tricky to eliminate all references to a class. And besides, repeatedly forcing the GC to run now is bad for overall performance.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!