WARNING: VERY UGLY "SOLUTION"
Given these 2 modules loaded with different DexClassLoaders (on different occasions, by different threads, etc):
- Module-1 (module-1.jar with class ClassModule1)
- Module-2 (module-2.jar with class ClassModule2)
For ClassModule1 to "see" ClassModule2 instead of doing this:
Class class = Class.forName("com.example.app.ClassModule2", false, ClassModule1.class.getClassLoader());
One should use this:
ClassLoader dexClassLoader = new DexClassLoader(
manager.getPluginsFolder() + "Module-2.jar",
this.context.getApplicationContext().getFilesDir().getAbsolutePath(),
null,
ClassModule1.class.getClassLoader()
);
Class class = Class.forName("com.example.app.ClassModule2", true, dexClassLoader);
This is ugly because of few things:
- we are loading the module once again for sure because of the 2nd arg on forName() "true"
- we have to know the path to Module-2.jar which is not good because modules are being management by a ModuleManager and not by themselves (separation of responsibility)
At least Dalvik (DexClassLoader) is smart enough not to optimize the .jar before loading it, but use the cached version generated by previous a DexClassLoader instance.
I guess the problem lies in: "At run time, a class or interface is determined not by its name alone, but by a pair: its binary name (§4.2.1) and its defining class loader. Each such class or interface belongs to a single run-time package. The run-time package of a class or interface is determined by the package name and defining class loader of the class or interface." (reference: chapter 5 of the JVM spec at http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html).
Any help appreciated.