Conversation
|
I'll give this a closer look actually tomorrow |
| printer.print( | ||
| """ | ||
| let environment$ = try! JavaVirtualMachine.shared().environment() | ||
| environment$.interface.PushLocalFrame(environment$, \(paramCount * 2 + 4)) |
There was a problem hiding this comment.
we should be checking the result of the push, we may be OOMing the JVM here, and we'd pop the wrong frame because we didn't push one (!)
jint PushLocalFrame(JNIEnv *env, jint capacity);
Creates a new local reference frame, in which at least a given number of local references can be created. Returns 0 on success, a negative number and a pending OutOfMemoryError on failure.
if pushed != JNI_OK
and need to guard the pop the same...
We may suggest doing a withFrame pattern tbh: swiftlang/swift-java-jni-core#11
| // and call it. | ||
| // Size the frame to 1 ref per argument; no result ref needed for void calls. | ||
| let jniMethod = environment.interface.CallVoidMethodA! | ||
| environment.interface.PushLocalFrame(environment, Int32(countArgs(repeat each args) + 1)) |
There was a problem hiding this comment.
Again we need to check the result type, so I think we need a with... pattern here - proposing one here swiftlang/swift-java-jni-core#11
We were hitting "JNI ERROR (app bug): local reference table overflow (max=512)".
In order to improve this, I've added some
DeleteLocalRefsand explicitPush/Popof local frames to SwiftJava where I saw fit.These changes made our app stopping crashing with that error.
This also modifies the "implement Swift protocols in Java" generated wrappers, such that all calls are wrapped in a local frame to ensure that resources are cleaned up, as this might not be called from a JVM thread and be auto-cleaned.