We have a large app that's always running into the dread method count limit. I've been asked to come up with a way to let it do much more, including supporting plugins. Looking for ways to unload code, I ran across JNI Tips which says
Classes are only unloaded if all classes associated with a ClassLoader can be garbage collected, which is rare but will not be impossible in Android.
This did seem to imply that a plugin can be unloaded if you, say,
- use a new
DexClassLoader
for each .jar file, - only ever refer to the plugin through an interface reference, and
- null-out any copies of that interface reference when done.
So, I created a test case:
- I created a couple of trivial plugins, using a unique loader for each.
- I created a
ReferenceQueue<ClassLoader>
and created weak references to my two loaders, using that queue; I created/started a thread that loops indefinitely, doing a queue.remove()
and reporting. - I similarly created a
ReferenceQueue<Class<?>>
and created weak references to each plugin'sgetClass()
using the queue; I created/started another thread monitoring the class reference queue. - I create a thousand 1000x1000xARGB_8888 bitmaps to thoroughly force gc.
My monitoring threads seem to work - I saw loader2
get gc-ed when I used loader1
to load both plugins by mistake ;-) - but otherwise my threads stay silent, even on 4.3. Am I maybe missing something obvious in this test case, or is it still the case that the
Dalvik VM doesn't currently unload classes
as Google employee fadden says in Android: When do classes get unloaded by the system?