3

Android - Adding jar file dynamically to a ClassLoader like:

String strJarfile = "/data/data/com.example.classloader/files/apps/Calc/SumAndSub.jar";    
URLClassLoader sysloader = (URLClassLoader) ClassLoader
                .getSystemClassLoader();
        try
        {
            File f = new File(strJarfile);
            URL u = f.toURI().toURL();

            Class[] parameters = new Class[] { URL.class };
            Method method = URLClassLoader.class.getDeclaredMethod("addURL",
                    parameters);
            method.setAccessible(true);
            method.invoke(sysloader, new Object[] { u });
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

And, error:

Caused by: java.lang.ClassCastException: dalvik.system.PathClassLoader cannot be cast to java.net.URLClassLoader

This code work fine in java-core, but not with android. What is solution? Thanks,

Tuan Huynh
  • 566
  • 4
  • 13

3 Answers3

1
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();

ClassLoader.getSystemClassLoader()

will return the PathClassLoader as a ClassLoader, so the (URLClassLoader) will cause the exception.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

Hey this is a bit late but I was having trouble with this and was able to solve it by creating my own DexClassLoader. Here's an example function that works for me now:

private SomeClass loadSomeClassInJarFile(String pathToJar, String mainClassName, String codeCacheDir) {
    SomeClass instanceOfSomeClass = null;
    try {
        DexClassLoader classLoader = new DexClassLoader(
                                            pathToJar, 
                                            codeCacheDir, 
                                            null, 
                                            mClassLoader);

        Class<?> cls = classLoader.loadClass(mainClassName);
        Constructor<?> cs = cls.getConstructor();
        instanceOfSomeClass = (SomeClass) cs.newInstance();
    } catch (Exception ex) {
        // This isn't the right class
        Log.w(Tag, "Class " + mainClassName + " could not load because " + ex.getMessage());
    }

    return instanceOfSomeClass;
}

A couple notes about the above:

  • mClassLoader needs to be the class loader from your Android application and NOT the default class loader. You can get it from your Application class (.getClassLoader()).

  • codeCacheDir I got from my ApplicationContext (.getCodeCacheDir().getPath()) although it can be null on the more recent versions of Android.

Jim
  • 833
  • 6
  • 13
-2

The solution is not to assume that the system class loader is a URLClassLoader. There's nothing anywhere that says it is. If your code ever worked you got lucky.

user207421
  • 305,947
  • 44
  • 307
  • 483