簡體   English   中英

如何在JNI中識別方法?

[英]How method Identified in JNI?

在開發過程中,由於錯誤,我錯過了在函數中添加參數的機會。 但是本地jni調用中的相同函數具有參數。 但是它仍然從Java調用精確方法。

Java類Demo.java

  package jniexamples.rmi;

class Demo {
    private native void jBoolean();
    public static void main(String[] args) {
        new Demo().jBoolean();
    }
    static {
        System.load("jnidemo.so");
    }
}

Demo.c

 #include <jni.h>
#include <stdio.h>
JNIEXPORT void JNICALL
Java_jniexamples_rmi_Demo_jBoolean(JNIEnv *env, jobject ob,jint dtype)
{
    printf("first demo %d" , dtype);
    return;
}

結果:第一次演示-1579007728

即使方法簽名不同,我也很困惑,它如何調用jni方法?

C函數僅在鏈接期間和運行時通過名稱標識,因此Java將調用該函數,但不提供任何參數。

如果在調用C函數時提供的參數太少,則會調用未定義的行為,這意味着可能發生任何事情。 (在您的情況下,您獲得了看似隨機的值。)

用javah生成的頭文件,它將具有正確簽名的函數聲明。 如果包含生成的標頭,則編譯器可以將標頭中的簽名與.c文件中的簽名進行比較,如果它們不同,則在編譯時會發出錯誤。

非常簡短的場景將以另一種方式出現。 從Java調用jBoolean()時,JVM會注意到此方法是本地方法,並嘗試查找其實現。 在您的情況下,JVM通過用類和包名稱修飾jBoolean構造本機函數的名稱。 結果是字符串Java_jniexamples_rmi_Demo_jBoolean 然后,它嘗試使用dlsym()在進程的地址空間中找到具有該名稱的函數。 因此,在嘗試調用此功能之前,使用此功能加載本機模塊至關重要。 然后,如果可以的話dlsym()返回該函數的指針,但是請注意,該指針沒有有關實際函數簽名的信息,並且JVM僅使用Java中聲明的一個來推斷本機簽名。 然后,JVM根據推斷出的簽名調用您的本機函數。

結果-推斷的簽名與實際簽名之間的差異會導致未定義的行為,這可能會導致非常奇怪的事情,不僅會導致隨機參數值。 因此,這是一個好習慣-將javah生成的標頭包含在本機實現中。 如果您的實現之一具有與標頭中聲明的簽名不同的簽名,則此類標頭會使編譯出錯並出錯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM