ClassCastException because of classloaders?

10,905

Solution 1

You cannot cast between class loaders. Class identity is composed of fully qualified name and the class loader. Check class identity crysis here.

Solution 2

Yes, you are correct.

This often happens in OSGi projects, because of bad dependency management.

Solution 3

That's exactly the case. You can't use casting between classes loaded by different classloaders.

This question, "Cast across classloader" may make things clearer...

Share:
10,905
Sebastien Lorber
Author by

Sebastien Lorber

React expert & early adopter (January 2014) Freelance, working for Facebook/Meta as Docusaurus maintainer since 2020. Author of ThisWeekInReact.com, the best newsletter to stay up-to-date with the React ecosystem:

Updated on July 18, 2022

Comments

  • Sebastien Lorber
    Sebastien Lorber almost 2 years

    While playing with classloaders i got the following exception:

    Exception in thread "main" java.lang.ClassCastException: xxx.Singleton cannot be cast to xxx.Singleton
    

    Does this mean that an instance from a classloader is not castable to an class of another classloader?

    Check my code where i'm able to instanciate 3 singletons thanks to classloaders, even with the "" security.

    public static void main(String[] args) throws Exception {
            URL basePath = new URL("file:/myMavenPath/target/classes/");
    
        Object instance = getClassInstance(Singleton.class);
        System.out.println(instance);
        //
        Object instance2 = getClassInstance(
                new URLClassLoader( new URL[]{basePath} , null )
                        .loadClass("my.Singleton")
        );
        System.out.println(instance2);
        //
        Object instance3 = getClassInstance(
                new URLClassLoader( new URL[]{basePath} , null )
                        .loadClass("my.Singleton")
        );
        System.out.println(instance3);
    
        // Only the 1st cast is ok
        Singleton testCast1 = (Singleton) instance;
        System.out.println("1st cast ok");
        Singleton testCast2 = (Singleton) instance2;
        System.out.println("2nd cast ok");
        Singleton testCast3 = (Singleton) instance3;
        System.out.println("3rd cast ok");
    }
    
    private static Object getClassInstance(Class clazz) throws Exception {
        Method method = clazz.getMethod("getInstance");
        method.setAccessible(true);
        return method.invoke(null);
    }
    
    
    class Singleton {
    
        private static final Singleton INSTANCE = new Singleton();
    
        public static Singleton getInstance() {
            return INSTANCE;
        }
    
        private Singleton() {
            Exception e = new Exception();
            StackTraceElement[] stackTrace = e.getStackTrace();
            if (!"<clinit>".equals(stackTrace[1].getMethodName())) {
                throw new IllegalStateException("You shall not instanciate the Singleton twice !",e);
            }
        }
    
        public void sayHello() {
            System.out.println("Hello World ! " + this);
        }
    
    }
    
  • Soumen Chandra
    Soumen Chandra over 7 years
    Can java run identity Crysis though?