Skip to content

Cleanup local refs#616

Open
madsodgaard wants to merge 7 commits intoswiftlang:mainfrom
madsodgaard:localref-cleanups
Open

Cleanup local refs#616
madsodgaard wants to merge 7 commits intoswiftlang:mainfrom
madsodgaard:localref-cleanups

Conversation

@madsodgaard
Copy link
Contributor

@madsodgaard madsodgaard commented Mar 12, 2026

We were hitting "JNI ERROR (app bug): local reference table overflow (max=512)".

In order to improve this, I've added some DeleteLocalRefs and explicit Push/Pop of 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.

@madsodgaard madsodgaard requested a review from ktoso as a code owner March 12, 2026 12:03
@ktoso ktoso self-requested a review March 12, 2026 12:53
@ktoso
Copy link
Collaborator

ktoso commented Mar 12, 2026

I'll give this a closer look actually tomorrow

printer.print(
"""
let environment$ = try! JavaVirtualMachine.shared().environment()
environment$.interface.PushLocalFrame(environment$, \(paramCount * 2 + 4))
Copy link
Collaborator

@ktoso ktoso Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants