#include "tools_EncryptLib.h"
#include <iostream>
#include "yxyDES.h"
#include <string>using namespace std; //功能:读取文件得到密钥;
string getKey() {
char fileName[] = "C:\\key.txt";
ifstream in(fileName);
string line;
getline(in, line);
return line;
}//功能:将Java的byte数组转换为C   char   *;
char   *   jbyteArrayToChar(JNIEnv   *   env,   jbyteArray   bytes)
{
char   *   rtn   =   NULL;
jsize   len   =   env-> GetArrayLength(bytes);
printf("读取数据长度完成\r\n");
jbyte   *   arrayBody   =   env-> GetByteArrayElements(bytes,0);
if(len   >   0)
{
rtn   =   new   char[len+1];//(char   *)malloc(len+1);
memcpy(rtn,   arrayBody,   len);
rtn[len]=0;
}
printf("拷贝数据完成\r\n");
env-> ReleaseByteArrayElements(bytes,   arrayBody,   0);
printf("释放数据完成\r\n");
return   rtn;
} jstring stoJstring(JNIEnv* env, const char* pat)
{
       jclass strClass = env->FindClass("Ljava/lang/String;");
       jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
       jbyteArray bytes = env->NewByteArray(strlen(pat));
       env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
       jstring encoding = env->NewStringUTF("utf-8");
       return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
} JNIEXPORT jstring JNICALL Java_tools_EncryptLib_encrypt
(JNIEnv * env, jobject obj, jbyteArray data, jbyteArray key) {
char* pKey = jbyteArrayToChar(env, key);
char* pData = jbyteArrayToChar(env, data);
printf("读取数据完成\r\n");
yxyDES* my_des = new yxyDES();
my_des->InitializeKey(pKey,false);
my_des->EncryptAnyLength(pData,false);
printf("加密数据完成\r\n");
jstring ret = stoJstring(env, my_des->GetCiphertextAnyLength());
printf("数据格式转换完成\r\n"); //当运行到这里的时候,有时候jvm会崩溃掉,不知道是因何原因
delete[] pKey;  
    pData = NULL;
delete[] pData;  
    pData = NULL;
delete my_des;  
    my_des = NULL;
printf("释放内存完成\r\n");
return ret;
}/*JNIEXPORT jbyteArray JNICALL Java_java_lang_EncryptLib_decrypt
(JNIEnv * env, jobject obj, jbyteArray data, jbyteArray key) {
char* pKey = jbyteArrayToChar(env, key);
char* pData = jbyteArrayToChar(env, data); yxyDES* my_des = new yxyDES();
my_des->InitializeKey(pKey,false);
my_des->DecryptAnyLength(pData,false);
char* ret = my_des->GetPlaintextAnyLength();
int len = strlen(ret);
ret[len] = 0;
jbyteArray bytearray; 
bytearray = env->NewByteArray(len); 
env->SetByteArrayRegion(bytearray, 0, len, (const signed char *)ret); 
return bytearray;
}*/
JNIEXPORT jbyteArray JNICALL Java_tools_EncryptLib_getkey
(JNIEnv * env, jobject obj) {
string ret = getKey();
int len = ret.size();
jbyteArray bytearray; 
bytearray = env->NewByteArray(len); 
env->SetByteArrayRegion(bytearray, 0, len, (const signed char *)ret.c_str()); 
return bytearray;
}以上是我写的jni调用的dll部分的代码,运行的时候会出现jvm直接崩溃的问题,那位大侠给看看,是不是有内存泄漏或者什么问题。yxyDES是里面的加密类,先不考虑这个类里面有问题的情况,帮我看看我写的这个接口类有没有什么问题。不知道应该发java版还是c版,先发这里,希望有高人相助。

解决方案 »

  1.   

    //当运行到这里的时候,有时候jvm会崩溃掉,不知道是因何原因 
    delete[] pKey;  
        pData = NULL; //pKey = NULL?
    delete[] pData;  
        pData = NULL; 你delete了pKey但却没有把它置空,不知道是不是问题?
      

  2.   

    同意楼上的说法,你delete了pKey但却没有把它置空,应该是这个问题吧...
      

  3.   

    不是这个问题,哪里只是一格笔误,我改了之后jvm还是会出错。
      

  4.   

    哦,可以在函数里每次调用jni方法后,加上判断,看看jvm是否已经有异常抛出了。
    jclass strClass = env->FindClass("Ljava/lang/String;"); 
    if (strClass == NULL) { goto exp;}
          jmethodID ctorID = env->GetMethodID(strClass, " <init>", "([BLjava/lang/String;)V"); 
    if (ctorID == NULL) { goto exp;}
          jbyteArray bytes = env->NewByteArray(strlen(pat)); 
    if (bytes == NULL) { goto exp;}
          env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); 
          jstring encoding = env->NewStringUTF("utf-8"); 
    if (encoding == NULL) { goto exp;}
          return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
    exp:
        if ((*env)->ExceptionOccurred(env)) {
            (*env)->ExceptionDescribe(env);
        }
      

  5.   

    delete[] pKey;  
        pData = NULL; //pKey = NULL?
    delete[] pData;  
        pData = NULL; 
      

  6.   

    delete[] pKey;  
        pData = NULL; 
    delete[] pData;  
        pData = NULL; 
    delete my_des;  
        my_des = NULL; 
    pData 这个指针都设置为空了,以前的分配的内存就delete不掉了
    再调用delete[] pData;肯定报错
      

  7.   


    delete[] pKey; 
        pData = NULL; 这里只是一个笔误,我改了delete[] pKey; 
        pKey= NULL;
    delete[] pData; 
        pData = NULL;
    delete my_des; 
        my_des = NULL; 
    之后再次运行jvm还是会出错。
      

  8.   

    按xstom19说的调了一下,发现函数运行几次之后。
     jmethodID ctorID = env->GetMethodID(strClass, " <init>", "([BLjava/lang/String;)V"); 
    运行到上面这句的时候得到的ctorID = null,不知道是什么原因?高人快出现吧,救救我。
      

  9.   

    1.如果你加了env->ExceptionDescribe(),应该会打印出jvm的异常信息阿。看看到底抛了什么异常。
    是ExceptionInInitializerError还是OutOfMemoryError?或者是别的?
    2.你的方法里没有删除jvm new出来的对象,GC就不会回收这些对象了。
    你应在使用完他们后加上,
    env->DeleteLocalRef(bytes);
    env->DeleteLocalRef(encoding);这样才会被gc回收。
      

  10.   

    " <init>", 
    <init>前面多了一个空格,不知道是不是还是你的笔误
      

  11.   

    env->ExceptionDescribe()输出的信息是
    java.lang.NoSuchMethodError:  <init>,这是问为啥?
      

  12.   

    我一直是用GBK转换的,好像没有什么问题// 从 char* 转换到 jstring
    jstring char2JString(JNIEnv* env, char* str){
    // 定义变量
    jstring rtn = 0;
    jsize len = strlen(str);
    jclass clsstring = (*env)->FindClass(env,"java/lang/String");
    jstring strencode = (*env)->NewStringUTF(env,"GBK");
    jmethodID mid = (*env)->GetMethodID(env,clsstring, "<init>", "([BLjava/lang/String;)V");
    jbyteArray barr = (*env)->NewByteArray(env,len);
            //new encode string default "GBK"
            (*env)->SetByteArrayRegion(env,barr,0,len,(jbyte*)str);        //call new String(byte[] b,String encode)
            rtn = (jstring)(*env)->NewObject(env,clsstring,mid,barr,strencode);
            return (rtn);
    }
      

  13.   

    把空格去了试试,但是这样应该每次都是NoSuchMethodError才对啊。
    为什么你是运行了几次后才这样呢,比较奇怪。
      

  14.   

    原来是多了一个空格呀,我直接copy的,也没细看。不过改之后还有问题,估计应该是加密函数内部存在内存泄漏的问题,谢谢大家帮忙。