fix(android): stop crash when USB is first used off the main thread - #42
Merged
Merged
Conversation
fd_bridge resolved UsbNative with FindClass on the first call, which runs on a Rust thread attached via attach_current_thread. Such threads use the system class loader, so the lookup throws ClassNotFoundException; the pending exception survives the early return and ART kills the app when the thread detaches (e.g. on the first available_ports call). nativeInit is a static native method on UsbNative, so its jclass argument is the class itself, resolved by the app class loader. Keep a global ref to it there and drop the thread-dependent FindClass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
s00d
added a commit
that referenced
this pull request
Sep 11, 2026
Log new_global_ref / get_java_vm errors, distinguish not-ready messages, and add worker-thread enumerate smoke for #42. Co-authored-by: Cursor <cursoragent@cursor.com>
Owner
|
Published in 3.0.7 (release). Cubic follow-ups from this review are in ( Also on |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On Android, our app crashed the moment it listed serial ports, because it calls
available_portsfrom an async Tauri command (a tokio worker thread):fd_bridge::cache()looks upUsbNativewithFindClassthe first time it is used, on whatever thread gets there first. On a thread Rust attached withattach_current_thread, JNI uses the system class loader, which can't see app classes, so the lookup fails. The error is still pending when?returns early, so ART kills the app when the thread detaches. It only works if the first USB call happens to come from the main thread (e.g. the sync JS commands). Any call from async commands, tokio tasks or spawned threads crashes, and so could the port IO that now runs off the main thread.The fix:
nativeInitis a static native method onUsbNative, so itsjclassargument is the class itself, already resolved by the app class loader. The patch keeps a global ref to it there, next to where the JVM is stored, and drops the thread-dependentFindClass. The public API doesn't change. As before, calls that run beforebind()return "JNI not initialized".Testing
available_portsfrom a tokio worker. After it, enumeration runs ontokio-rt-workerand returns normally, with nothing in the crash buffer.cargo fmt --all -- --checkpasses.cargo clippy -p tauri-plugin-serialplugin --target aarch64-linux-android --lib -- -D warningspasses.--all-targetsforaarch64-linux-androidfails to compile the lib tests (unresolvedcrate::AtResultFormat, etc.). That happens identically onmain, so it's unrelated to this change.🤖 Generated with Claude Code
Summary by cubic
Fixes an Android crash when serial ports are first used from a non-main thread by caching the
UsbNativeJNI class innativeInitinstead of looking it up withFindClasson first use.FindClassuses the system class loader, which can't see app classes, so the lookup fails withClassNotFoundExceptionand ART kills the app at thread detach.nativeInitis a static native method onUsbNative, so itsjclassargument is already resolved by the app class loader; the fix keeps a global ref there.bind()still return "JNI not initialized".Written for commit 0173a5f. Summary will update on new commits.