lundi 16 septembre 2019

java.lang.InstantiationError when creating instance of static inner class with Objenesis

I am trying to create a utility method that should be able to deep-clone any object. (Object.clone() only works on Object implementing Cloneable and I heard it's flawed anyways.)

I am using Objenesis to create new instances of objects without the use of constructors.

However, when trying to clone a JFrame I get the following Exception:
(using this class because I think it should be a good and complex test)

java.lang.InstantiationError: [Ljava.util.concurrent.ConcurrentHashMap$Node;
    at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
    at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)

I am open to any solution, not necessarily limited to Objenesis.

My Code:

private static ObjenesisStd OBJENESIS = new ObjenesisStd();

@SuppressWarnings("unchecked")
public static <T> T clone(T object, boolean deep){
    if(object == null){
        return null;
    }else{
        try {
            T clone = (T) OBJENESIS.newInstance(object.getClass());
            List<Field> fields = ReflectionUtil.getAllFieldsInHierarchy(object.getClass());
            for(Field field : fields){
                boolean isAccessible = field.isAccessible();
                boolean isFinal = ReflectionUtil.isFinal(field);
                field.setAccessible(true);
                ReflectionUtil.setFinal(field, false);
                Class<?> type = field.getType();
                if(!deep || type.isPrimitive() || type == String.class){
                    field.set(clone, field.get(object));
                }else{
                    field.set(clone, clone(field.get(object), true));
                }
                field.setAccessible(isAccessible);
                ReflectionUtil.setFinal(field, isFinal);
            }
            return clone;
        } catch (Throwable e) {
            e.printStackTrace();
            //throw new RuntimeException("Failed to clone object of type " + object.getClass(), e);
            return null;
        }
    }
}


public static void main(String[] args) {
    GetterSetterAccess access = new GetterSetterAccess(JFrame.class);
    JFrame frame = new JFrame("Test Frame");
    for(String attr : access.getAttributes()){
        System.out.println(attr + " " + access.getValue(frame, attr));
    }

    System.out.println("----------------------------------------------");
    frame = clone(frame, true);


    for(String attr : access.getAttributes()){
        System.out.println(attr + " " + access.getValue(frame, attr));
    }
}





Aucun commentaire:

Enregistrer un commentaire