Is it still the case that Android never unloads classes?
Asked Answered
J

1

8

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,

  1. use a new DexClassLoader for each .jar file,
  2. only ever refer to the plugin through an interface reference, and
  3. null-out any copies of that interface reference when done.

So, I created a test case:

  1. I created a couple of trivial plugins, using a unique loader for each.
  2. 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.
  3. I similarly created a ReferenceQueue<Class<?>> and created weak references to each plugin's getClass() using the queue; I created/started another thread monitoring the class reference queue.
  4. 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?

Jiujitsu answered 17/9, 2013 at 1:53 Comment(0)
W
1

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.

Wean answered 21/9, 2013 at 5:49 Comment(5)
Thanks, I didn't think I was missing anything, though in this case it sure would have been nice. Fwiw, unloading classes would make the method count limit a lot easier to live with.Jiujitsu
Maybe not -- if you're referring to the 64K method limit, it's on the number of methods that can be referenced from a single DEX file. This is a compile-time limit, not a runtime limit. The only practical limit on the number of methods that can be loaded in memory is imposed by the LinearAlloc size, which caused problems for Facebook in froyo and gingerbread (facebook.com/notes/facebook-engineering/…). Of course, with enough classes you'll eventually fill the heap.Wean
No, I'm talking about the total runtime limit, the one LinearAlloc imposes. Our guy who's been dealing with the dex size limit told me that it's only about 100,000 methods per process - not all that much bigger than the file limit, given that Zygote brings in a decent chunk of functionality. I haven't seen him be really wrong about anything in the three years I've known him, but there's a first time for everything. If the LinearAlloc is just an array of method pointers, even 5M would be over a million methods ... so it must be holding more than that. (I'll have to read some code on Monday.)Jiujitsu
Does anyone know if ART unloads classes?Calpe
At the "Evolution of ART" talk at Google IO 2016, they said that N will unload classes.Jiujitsu

© 2022 - 2024 — McMap. All rights reserved.