1. The article seems kind-of shallow. I didn't see any concrete (qualitative or quantitative) remarks about the "fast" part. I don't doubt you have reasons to do this - but I expected some information on what component are you writing using Rust + JNI, and how it helped? Or is it just a demo?
At some point, repeated calls into the JNI are counter-productive to performance, since the JIT can not optimize them. Pinning affecting garbage collection is another potential drawback if any of your rust calls are long lived. If we don't measure and just conclude "we are fast because rust is faster than Java, and we took average of both speeds", it's a disservice.
2. Also, I see unsafe for each call? I'd rather isolate this into a class / different file, since in JNI only few types of calls are possible. (method returning one of the primtive types, an object or `void`). This is the approach I took in dart jnigen. (Though there, the call is Dart -> Java, not Java -> Native language).
unsafe {
env.call_method_unchecked(
java_logger,
logger_method,
ReturnType::Primitive(Primitive::Void),
&[JValue::from(format_msg(record)).as_jni()]
);
}
3. I believe some details are missing here. What's native_add_one mapped to? And how is tokio futures awaited from Java? I believe that's the important part you should be presenting.
public CompletableFuture<Integer> add_one(int x) {
long futureId = native_add_one(x); // Call Rust
return AsyncRegistry.take(futureId); // Get CompletableFuture
}
4. Also please don't use ChatGPT for writing anything. It totally derails the reader by mentioning irrelevant details and long winded corporate conclusion at the end of every sentence.