Open lhoward opened 2 hours ago
As a test, I cached the class loader in JNI_OnLoad
, and implemented my own FindClass()
that used it. (I thought I might be able to swizzle the JNI env, which whilst ugly would be quite convenient, but no dice – not writable memory.)
This gets me a few steps further but plenty of things like as()
are broken. So this is a bit of a tricky one. I think this is going to come up in any non-trivial Android application because you're likely going to need to allocate Java objects from the Swift side (edit: and from multiple threads).
In theory this shouldn't be a problem if we resolve the classes directly within the native method entry point (as in, not JNI_OnLoad but the first API call). Needs more investigation at this end, ISTR perhaps classes were visible in OnLoad but not from application methods. Gah.
Maybe we could have an optional protocol a Swift class could adopt that returns the preferred class loader as a static variable. That should be fairly easy to prototype at least.
Android JVM class resolution is tricky, as which classes are resolvable depends not only on the JNI environment but also the stack frame.
From https://developer.android.com/training/articles/perf-jni:
Doing
FindClass()
lookups inJNI_OnLoad
isn't really viable unless JavaKit caches classes and we can ’poison’ the cache by resolving any classes we will need there. It'sis not ideal though as it requires a priori knowledge of all the application classes (I suppose, this could be done with a macro). Conversely, passing an instance of the class into functions that need it doesn't make for a great API. Neither of these is particularly ergonomic becausegetJNIClass()
can't be overridden (it's in an extension), so one ends up needing to reimplementdynamicJavaNewObjectInstance()
.Caching a reference to the ClassLoader object might be the best approach, this can be done in
JNI_OnLoad
(as long as you know the name of at least one application class), and then perhaps it could be an additional optional argument to initialisers. OrJNIEnvironment
becomes a class to which class loaders can be attached.Anyway, just flagging this as food for thought.