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?
The Dalvik VM still doesn't unload classes. The JNI Tips page is encouraging good behavior so your app doesn't break if the VM starts unloading classes someday.