2

I am creating a java application which uses JNI. One of the JNI function accept enum as parameter. But after the JNI uses the parameter java displays java.lang.NoSuchFieldError.

Here's the java code:

private int convert(JacsbclibLoader.BCTemplateEnvelopeType inputTemplateEnvelopeType,      JacsbclibLoader.BCTemplateDataType inputTemplateDataType, JacsbclibLoader.BCTemplateEnvelopeType outputTemplateEnvelopeType, JacsbclibLoader.BCTemplateDataType outputTemplateDataType, byte[] inputData, byte[] outputData, JacsbclibLoader.BCTemplateInfoType_1 suplementaryInfo)
{

    if(outputData != null)
        outputLength = outputData.length;

    status = _bclib.jBCConvertTemplate(inputTemplateEnvelopeType, inputTemplateDataType,inputData, inputData.length, outputTemplateEnvelopeType,                                    outputTemplateDataType, outputData, outputLength, suplementaryInfo);
    return status;
}

Here's the Native code in java:

public enum BCTemplateDataType
{
    BCT_NOT_SPECIFIED(-1),
    BCT_NONE(0),
    BCT_UPEK_LEGACY(1),
    BCT_UPEK_ALPHA(2),
    BCT_UPEK_BETA(3),
    BCT_UPEK_AUTO(4),
    BCT_ANSI(5),
    BCT_ISO_FMR(6),
    BCT_ISO_FMC_NORMAL(7),
    BCT_ISO_FMC_COMPACT(8),
    BCT_ABAPI(9),
    BCT_LAST(10);

    private int value;

    private BCTemplateDataType(int value)
    {
        this.value = value;
    }   
}

public int jBCConvertTemplate(BCTemplateEnvelopeType inputEnvelopeType,
                                  BCTemplateDataType inputDataType,
                                  byte[] inputData,
                                  int inputDataLength,
                                  BCTemplateEnvelopeType outputEnvelopeType,
                                  BCTemplateDataType outputDataType,
                                  byte[] outputData,
                                  int outputDataLength,
                                  BCTemplateInfoType_1 suplementaryInfo)
    {
        ret = BCConvertTemplate(inputEnvelopeType, inputDataType, inputData, inputDataLength, outputEnvelopeType, outputDataType, outputData, outputDataLength, suplementaryInfo);
        return ret;
    };

    private native int BCConvertTemplate(BCTemplateEnvelopeType inputEnvelope,
                                         BCTemplateDataType inputDataType,
                                         byte[] input,
                                         int inputLength,
                                         BCTemplateEnvelopeType outputEnvelope,
                                         BCTemplateDataType outputDataType,
                                         byte[] output,
                                         int outputLength,
                                         BCTemplateInfoType_1 suplementaryInfo);

Here's the JNI code in C++:

    JNIEXPORT jint JNICALL Java_JacsbclibLoader_BCConvertTemplate
  (JNIEnv *env, jobject obj, jobject inputEnvelope, jobject inputDataType, jbyteArray inputData, jint inputLength, jobject outputEnvelope, jobject outputDataType, jbyteArray outputData, jint outputLength, jobject suplementaryInfo)
{
    LoadLib();


    BCTemplateInfoType_1 supInfo;


    BCTemplateEnvelopeType eInputTemplateEnvelopeType = BCTE_NONE;
    BCTemplateEnvelopeType eOutputTemplateEnvelopeType = BCTE_NONE;

    BCTemplateDataType eInputTemplateDataType = BCT_NONE;
    BCTemplateDataType eOutputTemplateDataType = BCT_NONE;


    jbyte *inputTemplate = env->GetByteArrayElements(inputData, 0);
    jbyte *outputTemplate = NULL;

    if(outputData != NULL)
    {
        MessageBox(NULL,"outputData != NULL","",0);
        jbyte *outputTemplate = env->GetByteArrayElements(outputData, 0);
    }



    jclass cls = env->GetObjectClass(obj);
    jfieldID fIdInputLength = env->GetStaticFieldID(cls, "inputLength", "I");
    jfieldID fIdOutputLength = env->GetStaticFieldID(cls, "outputLength", "I");


    if(pConvertTemplate)
    {


        /*int inputEnvelopeType;
        int inputEnvelopeDataType;
        int outputEnvelopeType;
        int outputEnvelopeDataType;*/

        /*jclass envelopeTypeClass = env->FindClass("JacsbclibLoader");
        MessageBox(NULL,"3.1","",0);
        jmethodID inputEnvelopeGetValueMethod = env->GetMethodID(envelopeTypeClass, "getValue", "I()");
        MessageBox(NULL,"3.2","",0);
        jint inputEnvelopeValue = env->CallIntMethod(inputEnvelope, inputEnvelopeGetValueMethod);

        MessageBox(NULL,"3.3","",0);
        eInputTemplateEnvelopeType = (BCTemplateEnvelopeType)inputEnvelopeValue;
        MessageBox(NULL,"3.4","",0);*/

        jclass inputEnvelopeClass = env->GetObjectClass(inputEnvelope);
        jclass inputEnvelopeDataTypeClass = env->GetObjectClass(inputDataType);
        jclass outputEnvelopeClass = env->GetObjectClass(outputEnvelope);
        jclass outputEnvelopeDataTypeClass = env->GetObjectClass(outputDataType);

        if(suplementaryInfo != NULL)
        {
            MessageBox(NULL,"4","",0);

            int ver;
            int captureCbeffpId;
            int captureEquiptCompliance;
            int captureEquiptId;
            int imgWidth;
            int imgHeight;
            int imgHorizontalResolution;
            int imgVerticalResolution;
            int fingerPos;

            jclass suplementaryClass = env->GetObjectClass(suplementaryInfo);

            jfieldID fIdVersion = env->GetFieldID(suplementaryClass, "version", "I");
            jfieldID fIdCaptureCbeffpid = env->GetFieldID(suplementaryClass, "captureCBEFFPid", "I");
            jfieldID fIdCaptureEquipmentCompliance = env->GetFieldID(suplementaryClass, "captureEquipmentCompliance", "I");
            jfieldID fIdCaptureEquipmentId = env->GetFieldID(suplementaryClass, "captureEquipmentId", "I");
            jfieldID fIdImageWidth = env->GetFieldID(suplementaryClass, "imageWidth", "I");
            jfieldID fIdImageHeigth = env->GetFieldID(suplementaryClass, "imageHeight", "I");
            jfieldID fIdImageHorizontalResolution = env->GetFieldID(suplementaryClass, "imageHorizontalResolution", "I");
            jfieldID fIdImageVerticalResolution = env->GetFieldID(suplementaryClass, "imageVerticalResolution", "I");
            jfieldID fIdFingerPosition = env->GetFieldID(suplementaryClass, "fingerPosition", "I");

            ver = env->GetIntField(suplementaryInfo, fIdVersion);
            captureCbeffpId = env->GetIntField(suplementaryInfo, fIdCaptureCbeffpid);
            captureEquiptCompliance = env->GetIntField(suplementaryInfo, fIdCaptureEquipmentCompliance);
            captureEquiptId = env->GetIntField(suplementaryInfo, fIdCaptureEquipmentId);
            imgWidth = env->GetIntField(suplementaryInfo, fIdImageWidth);
            imgHeight = env->GetIntField(suplementaryInfo, fIdImageHeigth);
            imgHorizontalResolution = env->GetIntField(suplementaryInfo, fIdImageHorizontalResolution);
            imgVerticalResolution = env->GetIntField(suplementaryInfo, fIdImageVerticalResolution);
            fingerPos = env->GetIntField(suplementaryInfo, fIdFingerPosition);

            memset(&suplementaryInfo, 0x00, sizeof(suplementaryInfo));

            supInfo.version = ver;
            supInfo.captureCBEFFPid = captureCbeffpId;
            supInfo.captureEquipmentCompliance = captureEquiptCompliance;
            supInfo.captureEquipmentId = captureEquiptId;
            supInfo.fingerPosition = fingerPos;
            supInfo.imageHeight = imgHeight;
            supInfo.imageHorizontalResolution = imgHorizontalResolution;
            supInfo.imageVerticalResolution = imgVerticalResolution;
            supInfo.imageWidth = imgWidth;

        }

        returnStatus = pConvertTemplate(eInputTemplateEnvelopeType, 
                                       eInputTemplateDataType, (const void *)inputTemplate, (uint32)inputLength, 
                                       eOutputTemplateEnvelopeType, 
                                       eOutputTemplateDataType, 
                                       outputData != NULL ? (void *)outputTemplate : NULL,                                     
                                       (uint32 *)&outputLength,
                                       suplementaryInfo != NULL ? (const void *)&supInfo : NULL);

        env->SetStaticIntField(cls, fIdOutputLength, outputLength);   // It also crashes in windows7

        return returnStatus;

    }
    else
        return returnStatus;
}

and here's the enum of the third party library in which JNI referring to:typedef enum _tag_BCTemplateDataType { BCT_NOT_SPECIFIED = -1,
BCT_NONE = 0,
BCT_UPEK_LEGACY,
BCT_UPEK_ALPHA,
BCT_UPEK_BETA,
BCT_UPEK_AUTO,
BCT_ANSI,
BCT_ISO_FMR,
BCT_ISO_FMC_NORMAL,
BCT_ISO_FMC_COMPACT,
BCT_ABAPI,
BCT_LAST
} BCTemplateDataType;

BebzSusuma
  • 71
  • 1
  • 3
  • 7
  • Is the exception thrown by `status = _bclib.jBCConvertTemplate(inputTemplateEnvelopeType, inputTemplateDataType,inputData, inputData.length, outputTemplateEnvelopeType, outputTemplateDataType, outputData, outputLength, suplementaryInfo);` ? – FrancescoDS Aug 06 '13 at 09:06
  • The exception is thrown after that function. Please note that there is no command following that. – BebzSusuma Aug 06 '13 at 09:09
  • What does pConvertTemplate do? – Joni Aug 06 '13 at 09:31
  • It convert the data being passed to the jni. (Sorry if I cannot explain it further. Its kinda confidential). It calls a function from a third party library. BC_DECL_API_FUNC(sint32, BCConvertTemplate, ( IN BCTemplateEnvelopeType inputEnvelope, IN BCTemplateDataType inputDataType, IN const void * pInput, IN uint32 inputLength, IN BCTemplateEnvelopeType outputEnvelope, IN BCTemplateDataType outputDataType, INOUT void * pOutput, INOUT uint32 * pOutputLength, IN const void * pSuplementaryInfo )); – BebzSusuma Aug 06 '13 at 09:35

1 Answers1

1

as pointed out in these questions, NoSuchFieldError usually occurs when calling GetFieldId with a wrong field name i.e. the name used in the C code does not match the field as defined in Java (including L at the front, full package and class name, field name and trailing semicolon) :

JNI: NoSuchFieldError

Get object from an object with JNI in C

Correct call should look something like :

jfieldID data = (*env)->GetFieldID(env, some_class, "data", "Lorg/someapp/SomeClass$_data;");

I would double check the code in pConvertTemplate for errors of this type - or post it for us to inspect.

Community
  • 1
  • 1
Graham Griffiths
  • 2,196
  • 1
  • 12
  • 15
  • I modified the my code above to show the whole content of JNI function – BebzSusuma Aug 06 '13 at 09:48
  • the GetFieldId calls should look more like this : jfieldID data = (*env)->GetFieldID(env, some_class, "data", "Lorg/someapp/SomeClass$_data;"); – Graham Griffiths Aug 06 '13 at 09:51
  • I tried that but no luck – BebzSusuma Aug 06 '13 at 10:36
  • much the same thing for GetStaticFieldID ? I would suggest sprinkling log / printf statements though your pConvertTemplate code to see where it throws an exception – Graham Griffiths Aug 06 '13 at 10:47
  • GetFieldID / GetStaticFieldID will return null if they fail to find the field, as per the docs : http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html so you can check for this – Graham Griffiths Aug 06 '13 at 10:53
  • I actually I put lots of messageBox to know where it breaks but the error occurs after calling the dll. – BebzSusuma Aug 06 '13 at 10:56
  • that is strange. Can we see the stack trace, to see where exactly it is triggered? – Graham Griffiths Aug 06 '13 at 11:04
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/34900/discussion-between-bebzsusuma-and-graham-griffiths) – BebzSusuma Aug 06 '13 at 11:08
  • sorry, not possible from my office...firewall etc – Graham Griffiths Aug 06 '13 at 11:12
  • Here's the part of stack trace. Its too long. Exception in thread "AWT-EventQueue-0" java.lang.NoSuchFieldError: fingerPosition at JacsLoader.BCConvertTemplate(Native Method) at JacsbclibLoader.jBCConvertTemplate(JacsLoader.java:258) at SampleCode.convert(SampleCode.java:766) at SampleCode.enroll(SampleCode.java:558) at SampleCode.access$4(SampleCode.java:467) at SampleCode$6.actionPerformed(SampleCode.java:220) – BebzSusuma Aug 07 '13 at 01:16
  • I try to put some exception handling in my JNI. something like this: jclass inputEnvelopeClass = env->GetObjectClass(inputEnvelope); if (env->ExceptionCheck()) { MessageBox(NULL,"exception here","",0); } The message box is being displayed meaning there's really an exception. What's wrong with GetObjectClass()? – BebzSusuma Aug 07 '13 at 03:30