Skip to content

Migrate JavaCoder to swift-java-jni-core#14

Open
ybiletskyi wants to merge 1 commit into
mainfrom
dev/migrate-to-swift-java-jni-core
Open

Migrate JavaCoder to swift-java-jni-core#14
ybiletskyi wants to merge 1 commit into
mainfrom
dev/migrate-to-swift-java-jni-core

Conversation

@ybiletskyi

@ybiletskyi ybiletskyi commented Jun 11, 2026

Copy link
Copy Markdown

Note

High Risk
This is a full JNI stack swap affecting class loading, JVM registration, and string bridging; Android apps must register the shared JVM and may need captureContextClassLoader(), and subtle JNI behavior differences can break existing integrations.

Overview
Replaces the external readdle/java_swift dependency with swiftlang/swift-java-jni-core, while keeping a local java_swift library that re-exports the old JNI / JNICore / JNIObject surface on top of SwiftJavaJNICore. Package.swift moves to Swift tools 6.0, splits JavaCoder into its own target path, and publishes both JavaCoder and java_swift products.

JavaCoder gains JavaBridgeable.swift (Codable ↔ jobject, Throwable, and Error ↔ Java exception bridging) so SwiftJava codegen no longer needs Readdle’s Java runtime. CAndroidNDK imports are dropped from config/primitive files.

The shim adds JNIBootstrap.captureContextClassLoader() for Android class resolution from non-JVM threads and does not ship its own JNI_OnLoad (avoids clashing with SwiftJava). String encode/decode paths use UTF-16 NewString / GetStringChars instead of modified UTF-8, fixing supplementary-character handling.

Reviewed by Cursor Bugbot for commit 5b9e79d. Bugbot is set up for automated code reviews on this repo. Configure here.

Replace the readdle/java_swift dependency with swiftlang's official swift-java-jni-core (SwiftJavaJNICore), keeping JavaCoder's source effectively unchanged.
@ybiletskyi ybiletskyi requested a review from andriydruk June 11, 2026 10:59

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5b9e79d. Configure here.

let args = [jvalue(l: javaName)]
let clazz: jclass? = args.withUnsafeBufferPointer { ptr in
api.CallObjectMethodA(env, classLoader, loadClassMethodID, ptr.baseAddress)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

loadClass gets slash names

High Severity

When a context classLoader is set, FindClass resolves classes via ClassLoader.loadClass(String), but it passes the JNI internal name (slashes, e.g. java/lang/Integer) instead of the binary name Java expects (dots). Class lookup fails on Android after JNIBootstrap.captureContextClassLoader().

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b9e79d. Configure here.

let args = [jvalue(l: javaName)]
let clazz: jclass? = args.withUnsafeBufferPointer { ptr in
api.CallObjectMethodA(env, classLoader, loadClassMethodID, ptr.baseAddress)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nil method ID JNI call

Medium Severity

If GetMethodID for loadClass fails, loadClassMethodID stays nil but CallObjectMethodA is still invoked with that nil method ID when using the context class loader, which can crash native code or behave unpredictably.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b9e79d. Configure here.

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.

1 participant