Solution for the ClassCastException due to ClassLoader issue

后端 未结 5 554
既然无缘
既然无缘 2020-12-03 19:06

I have two ClassLoaders which loads the same class. So, obviously these can\'t cast to one another. But I need to access an object created in the other ClassLoader.

相关标签:
5条回答
  • 2020-12-03 19:30

    AFAIK, no, you can't cast an object of a class loaded by one class-loader in another class loader.

    • One solution would be to create a "common" class-loader which loads the classes to be used by your custom classloaders. So in your case, you'd have a new classloader which would load the given class and your custom classloaders would extend this classloader.
    • Another solution would be to pass around the "serialized" state between the two classloaders. Serialize one instance to a byte array and reconstruct the object in the other classloader by de-serializing the object stream.
    0 讨论(0)
  • 2020-12-03 19:30

    I think better option to just store byte array instead of object. While deserliazing, get byte array back and convert into object.

    I had the same issue and byte array approach worked.

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutput out = null;
        try {
            out = new ObjectOutputStream(bos);
            out.writeObject(cachedValue);
            byte b[] = bos.toByteArray();
    
            //Store in DB, file wherever here using b[]. I am not writing code to store it as it may vary in your requirement.
    
        } catch (IOException e) {
            e.printStackTrace();
        }
    

    Read from byte array:

    ByteArrayInputStream bis = new ByteArrayInputStream(<<read byte[] where you stored earlier>>);
        ObjectInput in = null;
    
        try {
            in = new ObjectInputStream(bis);
            <Your Class >cachedRes = ( Your Class) in.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    
    0 讨论(0)
  • Why you have 2 CloassLoaders, which loads the same class? This could be a programatic issue. It sounds like you are caching ClassLoader somewhere and re-use them in a wrong way. If this is not the case try a MultiClassLoader.

    Create a MultiClassLoader which includes multiple other classloader. These MultiClassLoader you can use to load all Classes you wish. But you have to create these MultiClassLoader at the very beginning and not when the classes are loaded.

    public class MultiClassLoader extends ClassLoader
    

    You would have a collection of classloaders and in the findClass(...) you iterate over all these registered loaders.

    protected Class findClass(String aName) throws ClassNotFoundException {
       for (Iterator iter = multiLoaders.iterator(); iter.hasNext();) {
          ClassLoader tmpLoader = (ClassLoader)iter.next();
          try {
             return tmpLoader.loadClass(aName);
          } catch (ClassNotFoundException e) {
          }
       }
       throw new ClassNotFoundException(aName);
    }
    
    0 讨论(0)
  • 2020-12-03 19:38

    The easiest way is to use reflection. This allow you to dó anything you Can dó in "normal" code.

    0 讨论(0)
  • 2020-12-03 19:48

    Reflection isn't that bad, and is appropriate here.
    Is this a Maven plugin, BTW?

    You'll want something like:

    Mojo mojo = (Mojo)descriptor.getClass().getMethod("getMojo").invoke(descriptor);
    

    I'm leaving out a lot - particularly exception handling - but this should lead you to the Javadoc you need. It's quite good, but read carefully.

    If you also have two Mojo classes, the cast will break, and you'll have to do more reflection to do whatever you need to do with the evil-twin Mojo.

    0 讨论(0)
提交回复
热议问题