Context issue, cross-referencing skiptools/skip#716 (full evidence there: symbol counts showing SwiftJNI statically linked into seven .so files with three competing JNI_OnLoad exports, disproven System.loadLibrary workaround, crash signature).
When an embedder statically links the jni-core runtime into more than one .so in the same process — which is what Skip Fuse's per-module linking does today — JNI.jni exists once per object, JNI_OnLoad initialises only the copy in the library the JVM loaded, and the first use from any other copy fatals at SwiftJNI.swift:1390 (String.fromJavaObject).
Probably a build/packaging question more than a bug in swift-java itself, but worth deciding where the invariant lives: should swift-java (a) document "exactly one copy per process" as a hard requirement, (b) expose an explicit re-initialisation / state-sharing hook for multi-.so embedders, or (c) ship the runtime as a dynamically-linkable core so embedders can share it? Happy to test a direction against our reproduction.
Context issue, cross-referencing skiptools/skip#716 (full evidence there: symbol counts showing SwiftJNI statically linked into seven
.sofiles with three competingJNI_OnLoadexports, disprovenSystem.loadLibraryworkaround, crash signature).When an embedder statically links the jni-core runtime into more than one
.soin the same process — which is what Skip Fuse's per-module linking does today —JNI.jniexists once per object,JNI_OnLoadinitialises only the copy in the library the JVM loaded, and the first use from any other copy fatals atSwiftJNI.swift:1390(String.fromJavaObject).Probably a build/packaging question more than a bug in swift-java itself, but worth deciding where the invariant lives: should swift-java (a) document "exactly one copy per process" as a hard requirement, (b) expose an explicit re-initialisation / state-sharing hook for multi-
.soembedders, or (c) ship the runtime as a dynamically-linkable core so embedders can share it? Happy to test a direction against our reproduction.