Java bindings for the Oniguruma regular expression library.
This repository publishes a JNI backend backed by the onig Rust crate and an FFM backend backed by the upstream C library.
Both modules are primarily designed to support syntax highlighting in IntelliJ-based IDEs through the textmate-core library.
A JNI wrapper implemented in Rust using the onig crate.
- Maven coordinate:
me.zolotov.oniguruma:oniguruma-jni - Java package:
me.zolotov.oniguruma.jni - JPMS module:
me.zolotov.oniguruma.jni - Documentation:
oniguruma-jni/README.md
A Java Foreign Function & Memory wrapper backed by the upstream C library.
- Maven coordinate:
me.zolotov.oniguruma:oniguruma-ffm - Java package:
me.zolotov.oniguruma.ffm - JPMS module:
me.zolotov.oniguruma.ffm - Documentation:
oniguruma-ffm/README.md
Both modules run the same JMH suite against shared inputs; the results are published continuously to the benchmark dashboard. The FFM binding is consistently ahead on operations dominated by per-call binding overhead. Where the time comes from:
- Cheaper native calls. FFM downcall handles compile to specialized stubs that are close
to a plain native call. A JNI native method pays for argument marshalling and the JNI
transition on every crossing, and the Rust side adds a
catch_unwindwrapper per call. - Results are read, not marshalled. After a match, FFM reads the offsets straight out of
the native
OnigRegionstruct and writes one Javaint[]. The JNI binding has to build the array through JNI functions (NewIntArray+SetIntArrayRegion), each itself a JNI crossing. - One copy per string, no pinning.
createStringin FFM is amallocand one copy into native memory. The JNI path enters a GC-critical section to pin the Java array, copies into the Rust heap, and boxes the result. - Cheaper error paths. A failed FFM compile builds one Java exception with the oniguruma diagnostic. The JNI path constructs a Rust error, formats it, and re-throws it across the boundary through the JNI exception machinery.
- Per-call allocations are reused. Both bindings reuse a per-thread match region instead of
calling
onig_region_new/onig_region_freearound every search; FFM also compiles patterns through a reused per-thread scratch block, so a smallcreateRegexperforms no allocation besides the returned handle wrapper.
Build all modules:
./gradlew buildBuild a single module:
./gradlew :oniguruma-jni:build
./gradlew :oniguruma-ffm:buildRun module benchmarks:
./gradlew :oniguruma-jni:jmh
./gradlew :oniguruma-ffm:jmhThe repository also contains an internal benchmarks project with shared JMH inputs and state.
Contributions are welcome! Please feel free to submit pull requests.
- Oniguruma – the regular expression library both backends build on, written and maintained by K.Kosako.
- rust-onig – the
onigcrate the JNI backend is implemented with, maintained by Will Speak, Ivan Ivashchenko and Vincent Prouillet.
This library is primarily intended for use with the textmate-core library in IntelliJ-based IDEs. While it can be used independently, the API is designed with this specific use case in mind.