Как вернуть вновь созданный объект класса Java в нативном для Android Java? - PullRequest
1 голос
/ 30 декабря 2011

Я пытаюсь вернуть недавно созданный объект класса Java на нативном для Android.После возврата объекта я сталкиваюсь с падением, когда пытаюсь получить доступ к внутренним объектам возвращаемого объекта.

На данный момент я просто использую функцию NewObject (), затем устанавливаю параметры и затем возвращаюсь из родной (язык языка) функции.

Нужно ли использовать какую-либо другую функцию дляинформировать JVM, а также сделать этот объект сборщиком мусора?

Я загрузил весь проект (проект Eclipse) в eSnips здесь. Нажмите здесь для проекта Android .Чтобы вы могли загрузить и просмотреть свой код.

Объект класса DataObject2.java будет возвращен из нативного.

UserDefinedObj.java равен

package example.nativeobj.obj;

public class UserDefinedObj {
    public int intPrimitive;

    @Override
    public String toString() {
        StringBuffer strBuf = new StringBuffer();

        strBuf.append("UserDefinedObj.intPrimitive: ");
        strBuf.append(intPrimitive);

        return strBuf.toString();
    }
}

Когда DataObject2.java равен

package example.nativeobj.obj;

public class DataObject2 {
    public int intData;
    public String strData;
    public UserDefinedObj usrDefData;

    @Override
    public String toString() {
        StringBuffer strBuf = new StringBuffer();

        strBuf.append("\n DataObject2.intData: ");
        strBuf.append(intData);
        strBuf.append("\n DataObject2.strData: ");
        strBuf.append(strData);
        strBuf.append("\n DataObject2.usrDefData: ");
        strBuf.append(usrDefData);
//      strBuf.append("\n UserDefinedObj.intPrimitive: ");
//      strBuf.append(usrDefData.intPrimitive);

        return strBuf.toString();
    }
}

Я сталкиваюсь с проблемой сбоя.

Но когда DataObject.java равен

package example.nativeobj.obj;

public class DataObject2 {
    public int intData;
    public String strData;
    public UserDefinedObj usrDefData;

    @Override
    public String toString() {
        StringBuffer strBuf = new StringBuffer();

        strBuf.append("\n DataObject2.intData: ");
        strBuf.append(intData);
        strBuf.append("\n DataObject2.strData: ");
        strBuf.append(strData);
        strBuf.append("\n DataObject2.usrDefData: ");
//      strBuf.append(usrDefData);
        strBuf.append("\n UserDefinedObj.intPrimitive: ");
        strBuf.append(usrDefData.intPrimitive);

        return strBuf.toString();
    }
}

, яне сталкивается с проблемой сбоя.

Разница в этой части кода, упомянутого ниже, пожалуйста, обратите внимание.

//      strBuf.append(usrDefData);
        strBuf.append("\n UserDefinedObj.intPrimitive: ");
        strBuf.append(usrDefData.intPrimitive);

и

        strBuf.append(usrDefData);
//      strBuf.append("\n UserDefinedObj.intPrimitive: ");
//      strBuf.append(usrDefData.intPrimitive);

кто-нибудь, пожалуйста, дайте мне знать об ошибке в моем коде.

Это мой родной код:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class example_nativeobj_api_Native */

#include "custom_debug.h"

//Paths
static const char *gDataObject1ClassPath = "example/nativeobj/obj/DataObject1";
static const char *gDataObject2ClassPath = "example/nativeobj/obj/DataObject2";
static const char *gUserDefinedObjectClassPath = "example/nativeobj/obj/UserDefinedObj";

/*
 * Class:     example_nativeobj_api_Native
 * Method:    func
 * Signature: (Lexample/nativeobj/obj/DataObject1;)Lexample/nativeobj/obj/DataObject2;
 */
JNIEXPORT jobject JNICALL Java_example_nativeobj_api_Native_func
  (JNIEnv *env, jclass cls, jobject dataobj1) {

    jobject dataObject2Obj = NULL;

    /* Get a reference to obj’s class */
    jclass dataObject1Cls = (*env)->GetObjectClass(env, dataobj1);
    jclass dataObject2Cls = (*env)->FindClass(env, gDataObject2ClassPath);
    jclass userDefinedObjCls = (*env)->FindClass(env, gUserDefinedObjectClassPath);

    DBG_LOG_INFO("func: clazz references of the dataObject1Cls: %u, dataObject2Cls: %u, userDefinedObjCls: %u",
                    dataObject1Cls, dataObject2Cls, userDefinedObjCls);
    if(dataObject1Cls == NULL || dataObject2Cls == NULL || userDefinedObjCls == NULL) {
        ERROR_LOG_INFO("func: Unable to get the clazz references of the dataObject1Cls: %u, dataObject2Cls: %u, userDefinedObjCls: %u",
                dataObject1Cls, dataObject2Cls, userDefinedObjCls);
    }

    //Get the field id of the User defined object class
    jfieldID userDefObjintFid;
    userDefObjintFid = (*env)->GetFieldID(env, userDefinedObjCls, "intPrimitive", "I");
    if (userDefObjintFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the intData of the userDefinedObjCls");
        return NULL; /* failed to find the field */
    }



    //Get the data from the dataobject1 class
    ////Get the object class
    jfieldID dataObj1IntFid; /* store the field ID */
    jfieldID dataObj1StrFid;
    jfieldID dataObj1UsrDefObjFid;

    jstring jstrDataObj1 = NULL;
    const char *strDataObj1 = NULL;
    jobject userDefObj = NULL;
    jint iData1ObjInt = 0;
    jint iUsrDefObjInt = 0;

    jthrowable exc;

    /* Look for the instance field s in cls */
    dataObj1IntFid = (*env)->GetFieldID(env, dataObject1Cls, "intData", "I");
    if (dataObj1IntFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the intData of the dataObject1Cls");
        return NULL; /* failed to find the field */
    }

    dataObj1StrFid = (*env)->GetFieldID(env, dataObject1Cls, "strData", "Ljava/lang/String;");
    if (dataObj1StrFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the strData of the dataObject1Cls");
        return NULL; /* failed to find the field */
    }

    dataObj1UsrDefObjFid = (*env)->GetFieldID(env, dataObject1Cls, "usrDefData", "Lexample/nativeobj/obj/UserDefinedObj;");
    if (dataObj1UsrDefObjFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the usrDefData of the dataObject1Cls");
        return NULL; /* failed to find the field */
    }

    ////Get the values of the data members
    iData1ObjInt = (*env)->GetIntField(env, dataobj1, dataObj1IntFid);
    DBG_LOG_INFO("func: iData1ObjInt: %d", iData1ObjInt);

    jstrDataObj1 = (*env)->GetObjectField(env, dataobj1, dataObj1StrFid);
    strDataObj1 = (*env)->GetStringUTFChars(env, jstrDataObj1, NULL);
    if (strDataObj1 == NULL) {
        ERROR_LOG_INFO("func: Unable to get the string of dataObject1Cls");
        return NULL;
    }
    DBG_LOG_INFO("func: c.s = \"%s\"\n", strDataObj1);

    ////Get the user defined object here
    userDefObj = (*env)->GetObjectField(env, dataobj1, dataObj1UsrDefObjFid);
    if(userDefObj == NULL) {
        ERROR_LOG_INFO("func: Unable to get the userDefObj from dataObject1Cls");
        goto cleanup1;
    }

    //////Get the data memebers of the user define object
    iUsrDefObjInt = (*env)->GetIntField(env, userDefObj, userDefObjintFid);
    DBG_LOG_INFO("func: iUsrDefObjInt: %d", iUsrDefObjInt);

    //Creating the new dataobject2 for returning from the function
    ////Get the method id for the constructor of the class
    jmethodID constructorId = (*env)->GetMethodID(env, dataObject2Cls, "<init>", "()V");
    if(constructorId == NULL) {
        ERROR_LOG_INFO("func: Unable to get the constructor for the dataObject2Cls");
        goto cleanup1;
    }

    ////Creating the new object for the class
    dataObject2Obj = (*env)->NewObject(env, dataObject2Cls, constructorId);
    if(dataObject2Obj == NULL) {
        ERROR_LOG_INFO("func: Unable to create an object for the class dataObject2Cls");
        exc = (*env)->ExceptionOccurred(env);
        if (exc) {
            /* We don't do much with the exception, except that
            we print a debug message for it, clear it, and
            throw a new exception. */
            (*env)->ExceptionDescribe(env);

        }
        goto cleanup1;
    }


    //Create the new dataobject2
    ////Get the field id's of the objectdata2 members
    jfieldID dataObj2IntFid; /* store the field ID */
    jfieldID dataObj2StrFid;
    jfieldID dataObj2UsrDefObjFid;

    dataObj2IntFid = (*env)->GetFieldID(env, dataObject2Cls, "intData", "I");
    if (dataObj2IntFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the intData of the dataObject2Cls");
        goto cleanup1; /* failed to find the field */
    }

    dataObj2StrFid = (*env)->GetFieldID(env, dataObject2Cls, "strData", "Ljava/lang/String;");
    if (dataObj2StrFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the strData of the dataObject2Cls");
        goto cleanup1; /* failed to find the field */
    }

    dataObj2UsrDefObjFid = (*env)->GetFieldID(env, dataObject2Cls, "usrDefData", "Lexample/nativeobj/obj/UserDefinedObj;");
    if (dataObj2UsrDefObjFid == NULL) {
        ERROR_LOG_INFO("func: Unable to get the usrDefData of the dataObject2Cls");
        goto cleanup1; /* failed to find the field */
    }

    ////Set the data member values
    //////Set the int field
    (*env)->SetIntField(env, dataObject2Obj, dataObj2IntFid, (iData1ObjInt+1));
    //////Set the string field
    jstring jstr_temp = (*env)->NewStringUTF(env, strDataObj1);
    if (jstr_temp == NULL) {
        ERROR_LOG_INFO("func: Unable to create the new string utf for the dataobj2class object");
        goto cleanup1; /* out of memory */
    }
    (*env)->SetObjectField(env, dataObject2Obj, dataObj2StrFid, jstr_temp);
    //////Set teh user define object
    ////////Get the method id for the constructor of the user defined class
    jmethodID usrDefConstructorId = (*env)->GetMethodID(env, userDefinedObjCls, "<init>", "()V");
    if(usrDefConstructorId == NULL) {
        ERROR_LOG_INFO("func: Unable to get the constructor for the dataObject2Cls");
        goto cleanup1;
    }

    ////////Creating the new object for the class
    jobject userDefObject = (*env)->NewObject(env, dataObject2Cls, usrDefConstructorId);
    if(!userDefObject) {
        ERROR_LOG_INFO("func: Unable to create an object for the class userDefObject");
        goto cleanup1;
    }
    DBG_LOG_INFO("func: userDefObject: %u", userDefObject);
    DBG_LOG_INFO("func: userDefObjintFid: %u", userDefObjintFid);
    DBG_LOG_INFO("func: dataObj2UsrDefObjFid: %u", dataObj2UsrDefObjFid);

    iUsrDefObjInt += 1;
    DBG_LOG_INFO("func: iUsrDefObjInt: %d", iUsrDefObjInt);
    (*env)->SetIntField(env, userDefObject, userDefObjintFid, iUsrDefObjInt);
    ////////Set this user defined object in the data object 2 class
    (*env)->SetObjectField(env, dataObject2Obj, dataObj2UsrDefObjFid, userDefObject);

    //////////////////////////////////////////////////////////////////////////
    //For verifying if the user defined object is set
//  jobject userDefObj_Temp = (*env)->GetObjectField(env, dataObject2Obj, dataObj2UsrDefObjFid);
//  if(userDefObj == NULL) {
//      ERROR_LOG_INFO("func: Unable to get the userDefObj from dataObject1Cls");
//      goto cleanup1;
//  }
//
//  //////Get the data memebers of the user define object
//  int iUsrDefObjInt_temp = (*env)->GetIntField(env, userDefObj_Temp, userDefObjintFid);
//  DBG_LOG_INFO("func: iUsrDefObjInt_temp: %d", iUsrDefObjInt_temp);

    //////////////////////////////////////////////////////////////////////////



    cleanup1:
    //Release all the handlers
    (*env)->ReleaseStringUTFChars(env, jstrDataObj1, strDataObj1);


    //return the dataobject 2
    return dataObject2Obj;
}


JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {

    JNIEnv *env = NULL;

    DBG_LOG_INFO("JNI_OnLoad: Called in libobjnative.so.....");

    if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
        ERROR_LOG_INFO("JNI_OnLoad: Failed to get the environment ising GetEnv");
        return -1;
    }


    return JNI_VERSION_1_4;
}


JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved) {

    DBG_LOG_INFO("JNI_OnUnload: Called in libobjnative.so.....");

    return;
}

Спасибо и С уважением,
SSuman185

1 Ответ

0 голосов
/ 05 января 2012

Обнаружена проблема.

Это была проблема при создании объекта UserDefinedObj

В нативном коде я делал вот так

jobject userDefObject = (*env)->NewObject(env, dataObject2Cls, usrDefConstructorId);

Поставлялссылка на «dataObject2Cls» для «UserDefinedObj»

Исправлена ​​ошибка при предоставлении «userDefinedObjCls»

jobject userDefObject = (*env)->NewObject(env, userDefinedObjCls, usrDefConstructorId);

С уважением,
SSuman185

...