I need to integrate this lib written in java in my rust crate.
So I'm trying to make a hello_world to call java function from rust. I'm using JNI bindings for rust. I'm based on docs and this question. But this is not working...
Once my java class is written I'm compiling with javac from hello folder and then generating c headers.
To compile
# from hello folder
javac HelloWorld.java
To generate headers
# from root project directory
javac main/java/org/hello/HelloWorld.java -h .
This is my project structure
|main/java/org/hello/
|-HelloWorld.java
|-HelloWorld.class
|src/
|-lib.rs
|-main.rs
|target/
|Cargo.toml
|org_hello_HelloWorld.h
this is my HelloWorld.java
package org.hello;
public class HelloWorld {
private static native String hello(String input);
static {
System.loadLibrary("java-ffi");
}
public static void main(String[] args) {
System.out.println("Hello world from java");
}
}
this is my lib.rs where i write the binding
use jni::JNIEnv;
use jni::objects::{JClass, JString};
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_org_hello_HelloWorld_hello(env: JNIEnv, class: JClass, _s: JString) {
let result = env.call_method(class, "main", "()V", &[]).unwrap();
println!("{:#?}", result);
}
this is my main.rs where i try to call the hello world
mod lib;
use jni::objects::JString;
use jni::{InitArgsBuilder, JNIVersion, JavaVM};
fn main() {
let jvm_args = InitArgsBuilder::new()
.version(JNIVersion::V8)
.option("-Xcheck:jni")
.build()
.unwrap();
let jvm = JavaVM::new(jvm_args).unwrap();
let _guard = jvm.attach_current_thread().unwrap();
let env = jvm.get_env().unwrap();
let class = env
.find_class("org/hello/HelloWorld")
.expect("Error on class");
let s = env.new_string("").unwrap();
lib::Java_org_hello_HelloWorld_hello(env, class, s);
}
this is the error when i make cargo run
thread 'main' panicked at 'Error on class: JavaException', src/main.rs:20:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Exception in thread "Thread-0" java.lang.NoClassDefFoundError: org/hello/HelloWorld
Caused by: java.lang.ClassNotFoundException: org.hello.HelloWorld
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
also based on this example from official repo i try to load the lib with java -Djava.library.path=mylib/target/debug/ HelloWorld
# from root project dir
java -Djava.library.path=target/debug main.java.org.hello.HelloWorld
but this gives me this error
Error: Could not find or load main class main.java.org.hello.HelloWorld
So, I don't understand what I'm missing. Can anyone explain me what is wrong with my code? And what is the correct form to make this?
I understand the problem is with the jvm which is not reading my java class, but I don't understand why...
additionally this is my Cargo.toml
[package]
name = "java-ffi"
version = "0.1.0"
edition = "2021"
[lib]
crate_type = ["cdylib"]
[dependencies]
[dependencies.jni]
version = "0.19"
features = [
"invocation",
"default"
]
Update:
I'm changing the package name of the java class, to match with folder path, from
package org.hello;
to
package main.java.org.hello;
So, the the error change.
When i make cargo run
thread 'main' panicked at 'Error on class: JavaException', src/main.rs:20:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Exception in thread "Thread-0" java.lang.UnsatisfiedLinkError: no java-ffi in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
at java.lang.Runtime.loadLibrary0(Runtime.java:871)
at java.lang.System.loadLibrary(System.java:1124)
at main.java.org.hello.HelloWorld.<clinit>(HelloWorld.java:7)
which is the same error when now i try load the library with
java -Djava.library.path=target/debug/ main.java.org.hello.HelloWorld
Exception in thread "main" java.lang.UnsatisfiedLinkError: no java-ffi in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
at java.lang.Runtime.loadLibrary0(Runtime.java:871)
at java.lang.System.loadLibrary(System.java:1124)
at main.java.org.hello.HelloWorld.<clinit>(HelloWorld.java:7)
which means the class are now 'recognized' but are bad linked, but i don't know why...
mavenorgradleto set up your Java project?.solib. But now I'm trying to understand how to config the java project