使用JNI调用graalvm原生构建共享库

问题描述 投票:0回答:0

我正在学习graalvm,我想知道我是否可以使用JNI来调用java原生构建的共享库?

假设有两个Java源代码,第一个会提前用graalvm编译成共享库,第二个会运行在JVM上,它会在运行时加载第一个源代码生成的共享库。我发现这在实践中很难,因为 JNI 和 graalvm native-build 生成的头文件的签名不同。

我有什么好的方法可以做到这一点吗?

两个源码及其生成的头文件如下:

LibEnvMap.java:

import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.c.function.CEntryPoint;
public class LibEnvMap {
    //NOTE: this class has no main() method

    @CEntryPoint(name = "Java_Main_HelloWorld")
    private static int HelloWorld(IsolateThread thread, Object object){
        System.out.println("Hello Native World!");
        return 0;
    }
}
#ifndef __LIBENVMAP_H
#define __LIBENVMAP_H

#include <graal_isolate.h>


#if defined(__cplusplus)
extern "C" {
#endif

int filter_env(graal_isolatethread_t*, char*);

#if defined(__cplusplus)
}
#endif
#endif

Main.java:

public class Main {
    static {
        System.load("/Users/nealshinoda/Repos/HelloWorld/out/production/HelloWorld/LibEnvMap.dylib");
    }

    private native int HelloWorld();
    public static void main(String[] args) {
        System.out.println("Hello world!");
        new Main().HelloWorld();
    }
}
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Main */

#ifndef _Included_Main
#define _Included_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Main
 * Method:    HelloWorld
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_Main_HelloWorld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

从两个头文件可以看出:它们的签名不兼容,而且参数的类型很难破解,因为它们都是机器生成的。

我想到的一个可能的解决方案是我可以使用另一个 C/C++ 代码作为“中间层”,然后调用堆栈可以是 JNI ==> C/C++ ==> graalvm 本机库。不过这个方案好像太复杂了,有没有更好的做法呢?

java-native-interface graalvm graalvm-native-image
© www.soinside.com 2019 - 2024. All rights reserved.