【问题标题】:Calling native method dynamically in Java在Java中动态调用本机方法
【发布时间】:2014-08-17 05:10:52
【问题描述】:

我正在制作软件(适用于 Android)以从传感器中读取仪表值。 该软件预计会经常接收更新,以支持更多传感器。读取这些传感器的仪表数据的功能是在应用程序运行时下载的本机库中实现的。

我有一个共享对象列表和一个应该调用的入口函数(返回值被保存):

libprintf.so,hookPrintf
libharx.so,hookHarx

每个库在运行时加载:System.loadLibrary("printf");

每个函数的签名如下所示:

public native int hookPrintf();
public native int hookHarx();

问题是我事先(在编译时)不知道必须加载哪些共享对象,因此我无法在 java 源代码中添加这些签名。

我尝试使用反射来动态调用方法,如下所示:

Method entryMethod = Expat.class.getMethod(hookMethod);
Object test = entryMethod.invoke(this);
System.out.writeln(test.toString());

但是,如果签名不存在,这仍然会失败并出现 NoSuchMethodException。有没有另一种方法可以调用原生方法而无需事先定义它们?

编辑: 使用 RegisterNatives 函数,我可以从共享对象动态注册我的函数,但这仍然需要在类中定义方法签名。 What does the registerNatives() method do?

【问题讨论】:

    标签: java c java-native-interface


    【解决方案1】:

    您可能拥有一个只有两个本地方法的 Java 类,并依赖 RegisterNatives 和 UnregisterNatives 并在运行时切换加载的本地实现。有了这个,我宁愿使用带有原生方法的原生包装库

    private static native void hook(String libName, String hookName);
    

    此包装器将使用 dlopen() 或 LoadLibraryEx() 并在必要时卸载外部库。

    在某些 JVM 中,您可以动态创建新类,但这很棘手。

    【讨论】:

    • 感谢 UnregisterNatives 通过切换实现的建议。我会去的。我确实相信您的方法签名应该包含 native 关键字。
    • 谢谢,原生 没有丢失
    【解决方案2】:

    您有一个基本的设计问题。我建议回过头来创建一个 JNI 库,它实现了一个单一的方法,比如 public native int createHook() 或类似的东西。然后根据某些条件在您的本机代码中做出选择。如果您仍希望/需要在运行时加载库,请为 libprintf.so 和 libharx.so 创建非 jni 库,并使用 dlopen 动态加载库或将库弱链接到 jni 库。

    【讨论】:

    • 我用我的具体用例更新了这个问题。这绝对是一种可能性,我想我只是希望它会更容易,Java 会接受通过 JNI 注册的函数。现在我正在通过创建一个包含 hookLib1() 直到 hookLib1000() 的存根文件来处理这个问题,以支持未来一年的更新,这不太理想。
    猜你喜欢
    • 2023-03-16
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2012-08-28
    • 2015-11-18
    相关资源
    最近更新 更多