0

I am trying to force some of the classes to be loaded using my custom class loader, the problem is after the loading the calling class still doesn't know about the class definition and tries to load it again, of course after that we have two different definitions of the class and assigning one to the other results in class cast exception. Any pointers or ideas how this can be fixed?

This is the calling class:

 CustomClassLoader loader = new CustomClassLoader(this.getPackageCodePath());
 Class<?> midletClass = loader.loadClass(className);
 midletClass.getMethod("InitEngine", Class.forName("android.app.Activity")).invoke(null, this);
 ms_MIDlet = (MIDlet)midletClass.newInstance();//ClassCastException

And this is the class loader itself

public class CustomClassLoader extends PathClassLoader
{
    public CustomClassLoader(String path)
    {
         super(path, getSystemClassLoader());//we set the parent to be the system class loader so the loading gets done in this class
    }

    @Override
    public InputStream getResourceAsStream(String resName)
    {
        //...do some resource loading here
    }
}
Anton Banchev
  • 541
  • 8
  • 28

1 Answers1

1

The calling class is running in some ClassLoader A. This classloader knows where to find and load MIDlet.class. Otherwise line 4 would produce a ClassNotFoundException for the cast.

You also use an instance of CustomClassLoader to load the Midlet.class.

On line 4 this blows up because you are casting the Midlet instance loaded by CustomClassLoader to a Midlet instances loaded by the ClassLoader A.

One solution is to make the CustomClassLoader logic delegate to ClassLoader A before loading a class itself. Something along the lines of first delegating a loadClass call to parentLoader.loadClass or getResourceAsStream to parentLoader.getResourceAsStream. If those calls fail then you can do your custom resource lookup.

This approach will make sure that all Midlet.class'es are actually loaded by the same classloader. You can check the delegation example at Java ClassLoader delegation model?

Community
  • 1
  • 1
toomasr
  • 4,731
  • 2
  • 33
  • 36
  • When I pass the Activity class to the midget class everything works even though they have different class loaders. The exception is thrown on the next line when I try to cast the midletClass to the local MIDlet. What I am doing now is save the returned object in an Object variable and make sure all the calls are done using the midletClass instance. – Anton Banchev May 27 '14 at 10:18
  • You do all invocations on the ms_MIDlet via reflection because you are unable to cast? – toomasr May 29 '14 at 06:40
  • Yes, it is not a huge problem as in reality ms_MIDlet is not used in the activity so much, I just use the activity to bootstrap the midget execution and then just forward any state changes to it when they happen (pause, resume, quit etc.) – Anton Banchev May 29 '14 at 07:12
  • Ok. You might see other problems in the future that stem from the fact of them being from different classloaders, for example IllegalAccessException. I'll mention an approach in my answer on how to remedy your situation. – toomasr May 29 '14 at 07:21