user1118764
user1118764

Reputation: 9845

Incoming string arguments cause JNI function to crash app if there are more than 2 jint arguments as well

I'm having a very weird problem. I have a JNI function that I've defined as such:

void Java_com_example_app_JNITest
(
    JNIEnv* env,
    jobject thiz,
    jint jSlotID,
    jint ulPinLen,
    jstring strStr1,
    jstring strStr2,
    jstring strStr3,
    jstring strStr4
)
{
    char* pszPin;
    char* pszStr1;
    char* pszStr2;
    char* pszStr3;
    char* pszStr4;
    int strLen;

    strLen = (*env)->GetStringUTFLength(env, strStr1);
    LOGD("copying Str1, len = %d", strLen);
    pszStr1   = (char*) (*env)->GetStringUTFChars(env, strStr1, NULL);
    LOGD(pszStr1);

    strLen = (*env)->GetStringUTFLength(env, strStr2);
    LOGD("copying Str2, len = %d", strLen);
    pszStr2   = (char*) (*env)->GetStringUTFChars(env, strStr2, NULL);
    LOGD(pszStr2);

    strLen = (*env)->GetStringUTFLength(env, strStr3);
    LOGD("copying Str3, len = %d", strLen);
    pszStr3   = (char*) (*env)->GetStringUTFChars(env, strStr3, NULL);
    LOGD(pszStr3);

    strLen = (*env)->GetStringUTFLength(env, strStr4);
    LOGD("copying Str4, len = %d", strLen);
    pszStr4   = (char*) (*env)->GetStringUTFChars(env, strStr4, NULL);
    LOGD(pszStr4);

    LOGD("All copied");
}

The JNI function does nothing, it just copies the incoming java arguments into corresponding C ones, and then returns.

The calling function calls it as such:

String temp1 = "123456";
String temp2 = "654321";
String temp3 = "lalala";
String temp4 = "hahaha";
int soPinLen = 6;
JNITest(256, soPinLen, temp1, temp2, temp3, temp4);

The Java function is declared as such:

private native void JNITest(int slotID, long pinLen, String soPin, String label, String temp1, String temp2) throws PKCS11Exception;

When I build the JNI file and run the app, it crashes on strLen = (*env)->GetStringUTFLength(env, strStr1);

The logcat output is:

E/dalvikvm( 7485): JNI ERROR (app bug): attempt to use stale global reference 0x6
E/dalvikvm( 7485): VM aborting
F/libc    ( 7485): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 7485 (rust.p11example)
I/ActivityManager( 2406): Process com.example.app (pid 7485) (adj 11) has died.

If I comment out the processing of strStr1 and move on to strStr2, it crashes with the following logcat output:

W/dalvikvm( 7662): JNI WARNING: received null jstring
W/dalvikvm( 7662):              in 
Lcom/gotrust/p11example/P11Example;.JNITest (IJLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V (GetStringUTFLength)
I/dalvikvm( 7662): "main" prio=5 tid=1 NATIVE
I/dalvikvm( 7662):   | group="main" sCount=0 dsCount=0 obj=0x41b39578 self=0x41b24a68
I/dalvikvm( 7662):   | sysTid=7662 nice=0 sched=0/0 cgrp=apps handle=1074798588
I/dalvikvm( 7662):   | state=R schedstat=( 445394159 50687413 915 ) utm=29 stm=15 core=3

If I comment strStr1 and strStr2, then the app runs perfectly, but the LOGD output shows that strStr3 is "123456" and strStr4 is "654321", which is incorrect since those values should be assigned to strStr1 and strStr2 instead.

Also, once I take away the ulPinLen from the JNI file and the corresponding Java function call, it works - I get the correct output in logcat.

Why can't I have more than 1 jint in the JNI argument list?

Thanks.

Upvotes: 1

Views: 1011

Answers (1)

fadden
fadden

Reputation: 52333

Your arguments aren't being passed correctly.

The message attempt to use stale global reference 0x6 is appearing because your soPinLen (whose value is 6) is taking the place of a string object reference. received null jstring has the same cause.

The problem is that your Java-language declaration does not match the native declaration. The method declaration can be seen in the error message:

Lcom/gotrust/p11example/P11Example;.JNITest (IJLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V

Note the argument section begins with IJ, indicating that the second argument (ulPinLen) is a 64-bit long. If you modify your native or Java declaration to match (i.e. make the second native argument jlong, or change the Java code to be int), the arguments should line up. As you discovered, removing the argument entirely has a similar effect.

Upvotes: 1

Related Questions