The Android NDK appears to support pinning down Java objects accessed from native code using GetByteArrayElements
and friends. But how long has this been the case? In other words, will my app avoid copying when possible on older devices too?
When did the Dalvik JNI start supporting pinning?
177 views Asked by Leif Arne Storset At
2
There are 2 answers
0
On
Glancing at the source code, the JNI library explicitly mentions pinning in code added in 2009 (so Android 2.1, API level 7). Before that, it looks like there wasn't a compacting garbage collector, so pinning would be a non-issue, but the library maintains a list of "global references" anyway.
So it looks like you're pretty safe!
Dalvik never had a GC that moved objects around. We did the necessary prep work, such as explicitly pinning objects, but at the point where development on the copying collector was getting serious (mid-2011) all development efforts shifted to Art.
The "global references" list holds all the JNI global references. In the early days the VM handed out raw pointers, so any reference visible to JNI needed to be pinned, which meant that all objects referenced by local or global JNI refs were immovable. In the ICS(?) release, Dalvik's JNI switched to indirect references, which meant that we only needed to lock down arrays of primitives that were explicitly pinned for direct access. (If you go back a few commits in the log from the change you linked to, you can see some of the work in progress.)
The indirect reference code didn't roll out for a couple of years because of some code deep in the core of the Android framework that assumed JNI references were unique unchanging values. The copying-collector work hadn't started, and indirect references cause a slight performance penalty, so there wasn't much motivation to mess with the bowels of the platform.