如何用jni配置弹簧?

时间:2016-04-16 14:09:26

标签: java eclipse spring java-native-interface

我要求将spring与一些用C语言编写的本机代码集成在一起,如果有人有将Spring与JNI集成的经验,那么我对它不熟悉并且对它没有任何想法,请与我分享。

提前致谢。

1 个答案:

答案 0 :(得分:1)

这个问题很模糊,但我可以提供一些我过去所做工作的建议。

  1. 忘记与" Spring"整合。专注于与Java集成,让Spring稍后帮助你。
  2. 对C
  3. 中的类型和内存分配非常非常小心
  4. Here这是一本关于JNI的书,我在工作时发现它非常有帮助。它有点过时但仍然有效
  5. 我在C中完成了大部分工作,然后在一个简单的单一方法中修补了Java。这样,我就用其母语完成了与现有代码的大部分集成。
  6. 为您的C代码提供一个主要方法,使您可以独立于Java测试C代码。然后,您可以将C文件编译为库(dll / so)和可执行文件。可执行文件可以通过参数来调用,以测试对现有调用的调用。
  7. 一般过程是。

    Java End

    public class statusBlock {
        /* A Java representation of a Status Block */
        private long errcode = 0;
        private long errref = 0;
        private String errmsg = "";
        private long[] TmidArray;
        private long evt_id = 0;
        private short IgViolation_severity = 0;
    }
    
    public class MyFunkyJNIClass {
        private Object response;
    
        /**
         * To generate the C-header for a native call use: javah -jni
         * example.package.MyFunkyJNIClass from target/classes folder.
         */
        private native int nativeExecuteFunction(int callType, Object payload, Object response);
    
        public MyFunkyJNIClass() {
            System.loadLibrary("theCLibrary");
        }
    }
    

    在上面的示例中,我使用System.loadLibrary加载代码的C端,并定义一些我可以从C代码填充的字段。要执行只调用 native 函数nativeExecuteFunction(1, "my payload", respObject);在C端,我可以使用第一个参数来选择要执行的操作。 当时简化了我的问题

    C面

    JNIEXPORT jint JNICALL Java_example_package_MyFunkyJNIClass_nativeExecuteFunction(JNIEnv *env, jobject this, jint CallType, jobject Payload)
    {
        // **** JNI Specific declarations for mapping ****
        jclass          cls, cls2, cls3;
        jmethodID       mid, mid2;
        jfieldID        fid;
        jint            rc = 0;
        jsize           js = 0;
        jbyte           jb;
        jobject         jobj, jobj2, jro;
        jobjectArray    jobjArray, jobjArray2;
    
        _svc_results    results;
    
        switch ((int)CallType)
        {
        case CALLTYPE1:       // 1
            DEBUG_PRINT("JNI Call Type 1 in progress...\n");
            // JNI mapping happens here
            stat = DoSomethingInC(args, &results);
    
            // Map from C structure (_statblk) to Java object
            if (stat == SUCCESS) {
                DEBUG_PRINT("\tMapping from C structure (_statblk) to Java object\n");
    
                cls  = (*env)->FindClass(env, "Lexample/package/statusBlock;");
                mid  = (*env)->GetMethodID(env, cls, "<init>", "()V"); if (mid == NULL) return -1;
                jro  = (*env)->NewObject(env, cls, mid); if (jro == NULL) return -1;
    
                fid  = (*env)->GetFieldID(env, cls, "errcode","I"); if (fid == NULL) return -1;
                (*env)->SetIntField(env, jro, fid, (jint)results.statblk.errcode);
                DEBUG_PRINT("\t\tMapped errcode: %d\n",results.statblk.errcode);
    
                fid  = (*env)->GetFieldID(env, cls, "errref","I"); if (fid == NULL) return -1;
                (*env)->SetIntField(env, jro, fid, (jint)results.statblk.errref);
                DEBUG_PRINT("\t\tMapped errref: %d\n",results.statblk.errref);
    
                fid  = (*env)->GetFieldID(env, cls, "errmsg","[B"); if (fid == NULL) return -1;
                jobj = (*env)->NewByteArray(env, MAX_ERR);
                (*env)->SetByteArrayRegion(env, (jbyteArray)jobj, 0, MAX_ERR, (jbyte*)results.statblk.errmsg);
                (*env)->SetObjectField(env, jro, fid, jobj);
                (*env)->DeleteLocalRef(env, jobj);
                DEBUG_PRINT("\t\tMapped errmsg: %s\n",results.statblk.errmsg);
    
                fid  = (*env)->GetFieldID(env, cls, "TmidArray","[I"); if (fid == NULL) return -1;
                jobj = (*env)->NewIntArray(env, (jsize)results.statblk.TmidArray.TmidArray_len);
                (*env)->SetIntArrayRegion(env, (jintArray)jobj, 0, 
                                          (jsize)results.statblk.TmidArray.TmidArray_len,
                                          (jint*)results.statblk.TmidArray.TmidArray_val);
                (*env)->SetObjectField(env, jro, fid, jobj);
                (*env)->DeleteLocalRef(env, jobj);
                DEBUG_PRINT("\t\tMapped TmidArray\n");
    
                fid  = (*env)->GetFieldID(env, cls, "evt_id","I"); if (fid == NULL) return -1;
                (*env)->SetIntField(env, jro, fid, (jint)results.statblk.evt_id);
                DEBUG_PRINT("\t\tMapped evt_id: %d\n",results.statblk.evt_id);
    
                cls  = (*env)->GetObjectClass(env, this);
                fid  = (*env)->GetFieldID(env, cls, "response","Ljava/lang/Object;"); if (fid == NULL) return -1;
                (*env)->SetObjectField(env, this, fid, jro);
    
                DEBUG_PRINT("\tMapping from C structure (_statblk) to Java object - DONE\n");
            } else {
                DEBUG_PRINT("JNI Call Type 1 in progress... Returning Error: %d\n", stat);
                return (jint)stat;
            }
    
            /* Free our native memory */
            cls  = (*env)->GetObjectClass(env, Payload);
            fid  = (*env)->GetFieldID(env, cls, "message","Ljava/lang/String;"); if (fid == NULL) return -1;
            jobj = (*env)->GetObjectField(env, Payload, fid);
            GPS_Free(results.statblk.TmidArray.TmidArray_val);
            GPS_Free(results.statblk.ErrorArray.ErrorArray_val);
            DEBUG_PRINT("JNI RTP Posting in progress... DONE\n");
            break;
        case PING:          // 2
            DEBUG_PRINT("No Java to C mapping required\n");
            DEBUG_PRINT("JNI Ping in progress...\n");
            stat = doPing();
    
            DEBUG_PRINT("No C to Java mapping required\n");
            // Stop null pointer exception if client tries to access the response object.
            cls  = (*env)->FindClass(env, "Lexample/package/EmptySerializableClass;");
            mid  = (*env)->GetMethodID(env, cls, "<init>", "()V"); if (mid == NULL) return -1;
            jro  = (*env)->NewObject(env, cls, mid); if (jro == NULL) return -1;
    
            cls  = (*env)->GetObjectClass(env, this);
            fid  = (*env)->GetFieldID(env, cls, "response","Ljava/lang/Object;"); if (fid == NULL) return -1;
            (*env)->SetObjectField(env, this, fid, jro);
            DEBUG_PRINT("JNI Ping in progress... DONE\n");
    
            return (jint)rpc_stat;
            break;
        default:
            fprintf(stderr,"Unknown call type\n");
            rc = -1;
            break;
        }
    
        return rc;
    }
    

    我可以继续,但只需要仔细阅读那本书。

    确实不需要与Spring进一步集成。您可以在@Component上粘贴@ServiceMyFunkyJNIClass注释。

    我希望这对你有所帮助。