rust-jni

Guides writing and reviewing Rust JNI bindings for JVM and Android interop.

2|1|Updated Aug 19, 2026
One-click install
npx skills add https://github.com/po4yka/rust-skills --skill rust-jni-po4yka
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: rust-jni
Source: https://github.com/po4yka/rust-skills/tree/main/skills/rust-jni
Command: npx skills add https://github.com/po4yka/rust-skills --skill rust-jni-po4yka

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? JNI has no compiler checking both sides of the boundary, so wrong method names, unguarded panics, unattached threads, and leaked local references fail only at run time on the device. This Skill provides the rules, templates, and triage tables to build and review Rust code that the JVM calls through JNI without run-time linkage failures or aborts. ## Core Features & Use Cases - Binding templates: RegisterNatives from JNI_OnLoad with the native_method! macro, plus #[jni_mangle] for name-based exports, with the exact panic-guard and error-policy patterns for jni 0.21 and 0.22. - Failure triage: Tables mapping UnsatisfiedLinkError, JNI DETECTED ERROR IN APPLICATION, local reference table overflow, and thread-detach aborts to their causes and fixes. - Threading and callbacks: Rules for attaching Rust-created threads, caching classes and method IDs in JNI_OnLoad, keeping env handles out of async tasks, and moving hot-path data via file descriptors or direct ByteBuffers. - Use Case: You are adding a native method to a Kotlin binding class backed by a Rust cdylib. Use this Skill to register it correctly, keep the JVM and Rust sides in one patch, and run the instrumentation checks that prove the binding. ## Quick Start Use the rust-jni skill to review my JNI_OnLoad and native method registrations for correctness against jni 0.22.

Frequently Asked Questions about rust-jni

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I bind a Rust native method to Kotlin with JNI?▼

Register every native method in JNI_OnLoad using the native_method! macro and register_native_methods, which checks Rust types against the descriptor at compile time and generates the panic guard. Declare the matching private external fun on the Kotlin binding class in the same patch.

Raw jni crate vs UniFFI for JVM bindings?▼

Use the raw jni crate for a small handle-based surface with a hot data path, and UniFFI 0.32.1 or later for a growing API with rich types or a second platform. Do not mix both styles on one binding class.

Why does UnsatisfiedLinkError say no implementation found for my native method?▼

No export or registration matches the class, method, or descriptor. Compare the tried names in the error with llvm-nm -D output, check for a Kotlin facade class like FooKt or $ in nested class names, and switch to RegisterNatives or #[jni_mangle].

Does FindClass work on threads created by Rust?▼

No. FindClass on a newly attached native thread uses the system class loader, which cannot see application classes. Resolve application classes in JNI_OnLoad, promote them to global references, and cache method IDs, or pass a ClassLoader from managed code.

Why does my Android app abort with local reference table overflow?▼

A loop created local references without a frame, and Android before API 26 aborts on overflow. Wrap every loop that creates Java objects in env.with_local_frame, sized at the per-iteration reference count plus a margin.

Can I hold a JNIEnv across an await point in async Rust?▼

No. The env handle is !Send + !Sync, and leaking or transmuting it to 'static is forbidden. Use the env synchronously, extract owned data, then spawn a task that captures a JavaVM clone and a global reference instead.