【问题标题】:Calling a Java class function from Cocoa with JNI使用 JNI 从 Cocoa 调用 Java 类函数
【发布时间】:2011-02-11 19:05:05
【问题描述】:

我真的很难弄清楚如何使用 JNI 从 Objective-C 调用 Java 函数。

首先我应该说我对 Java 知之甚少,但对 Obj-C 非常熟悉。我有一个 Java 类和一个方法,我需要从我的应用程序包中调用它。 jar 位于包中的 Resources 文件夹内,我将 NSJavaRoot 设置为 Content/Resources,检查了 NSJavaNeededNSJavaPath 包含 2 个 jar 文件的名称(主要的一个和一个依赖项)。

我正在使用对JNI_CreateJavaVM 的调用启动VM,然后尝试使用NSClassFromString 查找类,这感觉不对,但这是我在搜索中找到的唯一方法。我相信这种方法在使用已弃用的 Java 桥接器时是正确的,但我找不到任何使用 JNI 的示例或参考。

我的 Java 类如下所示:

package foo;

public class bar {

    public function dostuff() {

    }

}

作为应用程序流程的一部分,我需要调用一次dostuff()。有谁知道如何做到这一点?

谢谢, J

【问题讨论】:

    标签: java objective-c cocoa xcode java-native-interface


    【解决方案1】:

    由于 JavaBridge 已被弃用,您将不得不使用 JNI 来完成这一切。在 MacOS 上,您需要将 JavaVM.framework 添加到您的项目中,并且从您的源文件中,您要查找的标头是:

    #import <JavaVM/jni.h>
    

    接下来您需要设置 JavaVM。这可能很重要,具体取决于您的类路径和其他要求,但您走在正确的轨道上,因为这是您用来创建 JVM 的函数:

    JNI_CreateJavaVM(JavaVM **pJVM, void **pJNIEnv, void *args);
    

    接下来,您需要获取对您的类 foo.bar 的引用。这可以使用从 JNI_CreateJavaVM 传递的 pJNIEnv 来完成。你会想打电话:

    jclass myClass = JNIEnv->FindClass(JNIEnv, "foo/bar"); // Note the slashes replacing the dots...
    

    假设一切设置正确,您将获得对您的班级的引用。假设 foo.bar 有一个默认的无参数构造函数,你可以得到它的一个实例,像这样:

    jobject myFooBar = JNIEnv->NewObject(JNIEnv, myClass);
    

    现在您需要获取 doStuff 方法的 methodID。为此,您需要它的方法签名,您可以通过调用 javap 获得,如下所示:

    % javap -s foo.bar
    

    应该产生这样的输出:

    Compiled from "bar.java"
    public class foo.bar extends java.lang.Object{
    public foo.bar();
      Signature: ()V
    public void doStuff();
      Signature: ()V
    }
    

    然后您可以使用它来获取方法ID,您需要调用它。像这样:

    jmethodID mid = JNIEnv->GetMethodID(JNIEnv, myClass, "doStuff", "()V");
    

    假设所有这些事情都正确,那么你可以这样调用方法:

    JNIEnv->CallVoidMethod(JNIEnv, myFooBar, mid);
    

    并且该方法应该被调用。在任何这些阶段之后,您可能需要检查 VM 以查看是否存在异常。您可以通过以下方式检查是否发生异常:

    if (JNIEnv->ExceptionCheck(JNIEnv))
    {
        // Handle the exception...
    }
    

    如果你想要实际的 throwable,你可以使用 ExceptionOccurred JNI 方法得到它。

    所以,这里是最精简的部分:如何使用 JNI 从 Cocoa 调用 Java 方法。您将需要阅读 JNI 文档,尤其是有关理解全局引用和本地引用之间差异的部分。 (即让你的 Cocoa 端引用持续足够长的时间,以便在它们创建的范围之外被调用。)事实上,有一整章是关于常见错误和陷阱的,其中很多你都会遇到。

    http://java.sun.com/docs/books/jni/

    祝你好运!

    【讨论】:

    • 谢谢,这正是我最终通过反复试验所做的。希望这个非常清晰的描述能帮助其他陷入同样情况的人!
    • 非常感谢。这是一个非常棒的资源,因为我在其他任何地方都找不到如此直接的答案。
    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 2011-09-21
    相关资源
    最近更新 更多