当前位置: 首页 > 知识库问答 >
问题:

JNI调用静态方法。类对象是必需的吗?

郭永怡
2023-03-14

开始使用JNI从C调用静态java方法。具体来说,在获得一个jclass(使用FindClass)和一个jmethodID(使用GetStaticMethodID)之后,我继续调用一系列CallStatic*MethodA例程。事实证明,所有这些例程都将jclass作为第一个参数。我开始想为什么需要类对象:因为所有信息都是在GetStaticMethodID中提供的,所以JVM似乎不需要类对象来完成工作。然后,我尝试调用这些例程,同时为第一个参数传递NULL,调用成功。

我的问题:使用NULL类对象调用这些方法是否安全?

激励因素是:如果它确实合法,我将不必缓存类对象以供后续调用静态方法(同时记住html" target="_blank">调用NewGlobalRef…)。缓存jmethodID就足够了。

共有2个答案

高兴贤
2023-03-14

不,您不应该这样做,但重要的是要理解为什么在某些情况下,在调用静态方法时可以为类使用NULL。。。。至少在某些实现中。我当然不是java或jni方面的专家,但是如果你在https://android.googlesource.com/platform/art//master/runtime/jni/jni_internal。很明显,android jni没有引用CallStatic*方法的对象参数。。。

static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...)

唯一的问题是您不能保证所有平台上的行为,这只是一种可能实现的来源。

https://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp15982提到该方法必须来自clazz,所以它的其他实现很可能在调用之前进行二次检查,即使这是java的发布实现可能不会进行的性能权衡。

值得注意的是,静态方法只能访问静态成员,因此这种调用应该是安全的,但是jclass对象不是类的实例,它是类定义,可以很容易地用于诊断信息或其他与实际调用方法无关的东西。安全并存储jclass对象,这样做真的没有开销,因为它不是对象的实际html" target="_blank">实例。

田兴旺
2023-03-14

不,使用空(或无效)类指针调用此类静态函数绝对不安全。

您的实践可能会非常成功,例如,如果您的静态方法没有引用任何其他静态类成员。但是,如果您的静态java方法引用任何其他静态成员,您的JVM将需要有效的类指针。

例子:

以这个简单的Java演示MyTest.java

public class MyTest {
    public static void mymain() {
        System.out.println("Hello, World in java from mymain");
        System.out.println(magic_counter);   // this will cause a segfault if 
    }                                        // class pointer is null 
    private static int magic_counter=777; 
}

并使用以下JNI C片段调用它

... // JVM already loaded and initialised

jclass cls2 = env->FindClass("MyTest");
if(cls2 == nullptr) {
    cerr << "ERROR: class not found !";
}
else {
    cout << "Class MyTest found" << endl; 
    jmethodID mid = env->GetStaticMethodID(cls2, "mymain", "()V"); 
    if(mid == nullptr) 
        cerr << "ERROR: method void mymain() not found !" << endl; 
    else {
        env->CallStaticVoidMethod(cls2, mid);
        cout << endl;
    }
 }

调用GetStaticMachodID(nullptr,"mymain","()V");将失败。因为当mymain()执行时,它将尝试访问静态变量magic_number。然后,JVM将使用您提供的类指针,并假设它是加载的类返回的vaild指针。但是由于它为null,系统将分段故障。

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

  • 问题内容: 我有以下代码: 运行此命令时,我不断收到错误消息: 怎么解决呢? 问题答案: 您正在将 未绑定的 对象存储在字典中。通过访问名称作为类或实例上的属性,此类对象(以及对象,函数和对象)仅通过描述符协议进行绑定。直接访问类主体中的对象不是属性访问。 在 创建类 之后 创建字典(以便您将它们作为属性访问),或者显式绑定,或者在将它们存储在字典中之前提取原始函数。 注意,对对象的“绑定”仅意味

  • 本文向大家介绍PowerShell中调用.NET对象的静态方法、静态属性和类方法、类属性例子,包括了PowerShell中调用.NET对象的静态方法、静态属性和类方法、类属性例子的使用技巧和注意事项,需要的朋友参考一下 本文介绍在PowerShell中如何使用.NET对象,PowerShell内在支持大量的.NET对象。 调用类的静态方法 用中括号把类的名称括起来,然后输入两个冒号,然后再输入方法

  • 问题内容: 我刚刚开始模拟应用程序的不同层。我到了一个地步,我的一个模拟对象在调用最终类静态方法时返回NPE。有没有解决的办法? 例如 问题答案: 您必须同时使用PowerMock和Mockito。 我不明白您的代码段正在尝试做什么,但是以下代码段允许类的静态方法返回模拟的对象。也许这会为您指明正确的方向 在课堂上: 在您的测试方法中:

  • 本文向大家介绍php面向对象中static静态属性和静态方法的调用,包括了php面向对象中static静态属性和静态方法的调用的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php中static静态属性和静态方法的调用。分享给大家供大家参考。具体如下: 这里分析了php面向对象中static静态属性和静态方法的调用。关于它们的调用(能不能调用,怎么样调用),需要弄明白了他们在内存中存放位置

  • 问题内容: 说,我有一个带有SomeType的具有静态方法的Class对象的引用。有没有一种方法可以调用该方法而不先实例化SomeType?最好不要转义强类型。 编辑:好的,我搞砸了。 在这种情况下,someMethod()始终不能是静态的。 问题答案: 根据定义,静态方法是在类上调用的,而不是在该类的实例上调用的。 因此,如果您使用: 您没有实例化任何东西(不考虑由JVM处理并且超出了您的范围的