Search code examples
javaspringclassserializationclassloader

Instanceof returns false for same class after serialization


Instanceof returns false for same class after org.springframework.security.oauth2.common.util.SerializationUtils fasterxml deserialization in Spring boot application

new ObjectMapper().readValue(serialized, User.class);

Class

public class User implements Serializable {//...
}

Because new object getClass().getClassloader() returns different classloader, how to fix this and casting issue?


Solution

  • In this case you should compare the class names rather then using instanceof. Even if the classes are loaded by different class loaders the canonical names will be the same:

    public boolean haveSameCanonicalName(Object object, Class<?> clazz) {
         String actualClassName = object.getClass().getCanonicalName();
         String expectedClassName = clazz.getCanonicalName();
         return actualClassName.equals(expectedClassName);
    }
    

    And then you can use it like this:

    if (haveSameCanonicalName(user, User.class)) {
        // Do something here
    }
    

    UPDATE:

    If you still need to cast the object there is a workaround:

     public class CrossCastUtils {
    
        private final ObjectOutputStream oos;
        private final ObjectInputStream ois;
    
        public CrossCastUtils() throws IOException {
            final PipedOutputStream pos = new PipedOutputStream();
            final PipedInputStream pis = new PipedInputStream(pos);
            oos = new ObjectOutputStream(pos);
            ois = new ObjectInputStream(pis);
        }
    
        public <T> T cast(Object object) throws IOException, ClassNotFoundException {
            oos.writeObject(object);
            oos.flush();
            return (T) ois.readObject();
        }
    

    Try to run this test:

    @Test
    public void testCrossCast(){
        Object initial = ... // retrieve it as you did before
        User result = CrossCastUtils.cast(initial);
    
        assertFalse(initial instanceof User);
        assertTrue(result instanceof User);
    }