当前位置: 首页 > 面试题库 >

使用JNI从Cocoa调用Java类函数

李鸿
2023-03-14
问题内容

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

我首先要说的是,我对Java并不了解很多,但是对Obj-
C非常熟悉。我有一个带有单个方法的Java类,需要从我的应用程序包中调用它。该jar位于包中的Resources文件夹内,并且我将其NSJavaRoot设置为Content/Resources,它NSJavaNeeded被检查并NSJavaPath包含2个jar文件的名称(主要是一个,一个依赖)。

我正在通过调用来启动虚拟机JNI_CreateJavaVM,然后尝试使用该类来查找类,NSClassFromString这是错的,但这是我在搜索中找到的唯一方法。我相信使用不推荐使用的Java桥时此方法是正确的,但是我找不到使用JNI的任何示例或参考。

我的Java类如下所示:

package foo;

public class bar {

    public function dostuff() {

    }

}

我需要dostuff()在应用程序流程中致电一次。有谁知道如何做到这一点?

谢谢,J


问题答案:

由于不推荐使用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
}

然后,您可以使用它来获取methodID,您需要对其进行调用。像这样:

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/

祝好运!



 类似资料:
  • 我正在制作一个库应用程序,该应用程序使用谷歌断路器检测android中的本机崩溃。每当我的主端发生本机崩溃时,断路器都会调用以下回调。从这个回调中,我需要使用JNI在java类中调用一个静态val方法。 这是我的java方法: 在Android5.0之前,这一功能一直运行良好。但在Lollipop中,我无法调用我的java方法,因为我无法在Logcat控制台上看到“内部句柄异常”日志。 以下是我在

  • 这可能是一个真正的新手问题,但我正在编写一个Android应用程序,它需要使用一个用C编写的.so库。该.so由几个类组成,是通用C语言,而不是JNI语言。 除了JNI之外,有没有办法从AndroidJava应用程序调用C函数?我所看到的关于JNI的一切都表明,您必须重写本机代码以特定于JNI,如果只给您一个. so,那真是太不方便了。 在Android 4.0.3中,从java应用程序调用本机函

  • 我有一个Java应用程序,它合并了一些大文件。Java应用程序不在我的控制之下。Java应用程序的结果以大约90MB的大字符串返回给我的C程序,我在其中的一些算法中使用它。我多次调用execute方法。我的问题是,每次调用Java应用程序时,它都会保留更多内存,但不会释放内存。从这个垃圾收集和JNI调用问题中,我想到手动调用垃圾收集器,但它不会释放内存。有没有办法解决这个问题? 这是我的C程序

  • 因此,有人知道如何杀死一个线程,同时它调用任何JNI函数而不使用while循环。

  • 我正在尝试使用JNI注册表项将本机函数绑定到Java。如果函数在全局范围内,我可以轻松地绑定函数,并且它可以正常工作。 但是当我试图绑定一个C类成员函数Java回调不会被调用。 我的C函数的声明是这样的: Java函数如下所示。 我试图绑定的本机函数与我的注册本地方法调用在同一个类中。下面是我如何使用typedef定义函数指针并将其添加到JNINativemethod结构的一个片段。 我还使用了s

  • 我的C代码无法找到Java中的公共静态函数调用。它成功地找到了类,没有错误。 我试图将结果返回给回调方法。“5”稍后将被更复杂的内容取代。 我在StackOverflow上似乎也有类似的问题,但是到目前为止没有任何变化似乎有所帮助。也许我有逻辑错误? 我的JNI(更新#2): 此代码包含在此函数中调用的方法中: 我的Java(更新#1): 签名检查: javap-s-pcecutils 公共静态响