Java JNI本机代码上的内存泄漏

Java JNI本机代码上的内存泄漏,java,c,memory-leaks,java-native-interface,Java,C,Memory Leaks,Java Native Interface,我有一段JNI本地代码。当我们调用这个本地方法并运行其他请求时,jvm将崩溃 最有可能的是,这段JNI本机方法(c代码)中存在内存泄漏 任何机构都可以帮助检测以下代码中的内存泄漏 #include <stdio.h> #include <stdlib.h> #include <string.h> #include "fns_data.h" #include "fns_client.h" #include "sockRW.h" #include "/usr/lo

我有一段JNI本地代码。当我们调用这个本地方法并运行其他请求时,jvm将崩溃

最有可能的是,这段JNI本机方法(c代码)中存在内存泄漏

任何机构都可以帮助检测以下代码中的内存泄漏

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fns_data.h"
#include "fns_client.h"
#include "sockRW.h"
#include "/usr/local/include/jni.h"
#include "JNIiSearchLib.h"
#include "com_eds_wise_util_JNIiSearchLib.h"

JNIEXPORT jstring JNICALL
Java_com_eds_wise_util_JNIiSearchLib_jniFNSSearchClient (
    JNIEnv *env, jobject obj, jstring jip_addr, jint jport_number,
    jstring jfield, jstring jquery_str, jint jhitnum)
{
    HitIds           *hit_list   = NULL;
    hitListPktStruct *hitPkt     = NULL;
    int               hit_number = 0;
    int               i          = 0;
    int               fnsErrno   = 0;
    char             *result_str = NULL;
    jstring          rslt_str   = NULL;
    const char          *cip_addr   = NULL;
    const char          *cquery_str = NULL;
    char              errbuf[1024];

    cip_addr   = (*env)->GetStringUTFChars(env, jip_addr, 0);
    if (cip_addr == NULL) {
        return ((* env)->NewStringUTF (env, "Error: Cannot get IP address."));
    }

    cquery_str = (*env)->GetStringUTFChars(env, jquery_str, 0);
    if (cquery_str == NULL) {
        (*env)->ReleaseStringUTFChars (env, jip_addr, cip_addr);
        //(*env)->DeleteLocalRef(env, cip_addr);
        return ((* env)->NewStringUTF (env, "Error: Cannot get query string."));
    }
    printf ("[Java_JNILib_jniFNSSearchClient] ipaddress[%s] portnumber[%d]"
            " querystr[%s]\n\n", cip_addr, jport_number, cquery_str);

    /* Search and get back the handler & total hits
     */
    hit_list = fns_search_client0 ((char *)cip_addr, jport_number,
                                   "PN", (char *)cquery_str, &hit_number);
    fnsErrno = fns_error_message();
    if (fnsErrno) {
        printf ("Error %d during fns_search_client0()\n", fnsErrno);
        sprintf (errbuf, "Error: fns_search_client0() returns %d.", fnsErrno);

        rslt_str = (* env)->NewStringUTF (env, errbuf);

        (*env)->ReleaseStringUTFChars (env, jip_addr, cip_addr);
        (*env)->ReleaseStringUTFChars (env, jquery_str, cquery_str);
        //(*env)->DeleteLocalRef(env, cip_addr);
        //(*env)->DeleteLocalRef(env, cquery_str);

        fflush(stdout);
        return (rslt_str);
    }

    /* Display total hits
     */
    printf ("Total hits = %d\n", hit_number);

    /* Use the handler as parameter to retrieve the actual result
     */
    if (hit_number > 0) {
        fns_display_ids0 ((char *)cip_addr, jport_number, hit_list,
                          0, hit_number - 1, &hitPkt);
        fnsErrno = fns_error_message();
        if (fnsErrno) {
            printf ("Error %d during fns_display_ids0()\n", fnsErrno);
            sprintf (errbuf, "Error: fns_display_ids0() returns %d.", fnsErrno);
            rslt_str = (* env)->NewStringUTF (env, errbuf);

            if (hit_list) {
                FREE_STRING (hit_list);
            }
            (*env)->ReleaseStringUTFChars (env, jip_addr, cip_addr);
            (*env)->ReleaseStringUTFChars (env, jquery_str, cquery_str);
            //(*env)->DeleteLocalRef(env, cip_addr);
            //(*env)->DeleteLocalRef(env, cquery_str);

            fflush(stdout);
            return (rslt_str);
        }
    }

    /* Enumerate every item in the result list and display them.
     * The results are returned as a string to Java in the following manner:
     *
     * "[hitresult1|hitresult2|hitresult3|..|hitresultN]\0"
     *
     *     where hitresultN = 94-byte record
     *
     * [+string94+|+string94]+stringTerminator 
     */
    printf ("malloc[%d]\n", (hit_number * 95) + 3);

    result_str = malloc (((hit_number * 95)+3) * sizeof(char));
    if (result_str == NULL) {
        printf ("Out of memory, unable to malloc\n");
        rslt_str = (* env)->NewStringUTF (env, "Error: Out of memory, unable to malloc");

        if (hit_list) {
            FREE_STRING (hit_list);
        }
        if (hitPkt) {
            FREE_HITLIST_STRUCT (hitPkt);
        }
        (*env)->ReleaseStringUTFChars (env, jip_addr, cip_addr);
        (*env)->ReleaseStringUTFChars (env, jquery_str, cquery_str);
        //(*env)->DeleteLocalRef(env, cip_addr);
        //(*env)->DeleteLocalRef(env, cquery_str);

        fflush(stdout);
        return (rslt_str);
    }

    sprintf (result_str, "[");
    for (i = 0; i < hit_number; i++) {
        strcat (result_str, hitPkt->docNameList[i]);
        if (i != (hit_number - 1)) {
            strcat (result_str, "|");
        }
    }
    strcat (result_str, "]");

    printf ("\n\nFNS search result:[From Library]\n");
    printf ("%s\n\n",result_str);

    /* free the handler
     */
    if (hit_list) {
        FREE_STRING (hit_list);
    }

    /* free the result lists
     */
    if (hitPkt) {
        FREE_HITLIST_STRUCT (hitPkt);
    }

    /* prepare stuff for Java
     */
    rslt_str = (* env)->NewStringUTF (env, result_str);

    /* free our memory
     */
    if (result_str) {
        free (result_str);
    }
    (*env)->ReleaseStringUTFChars (env, jip_addr, cip_addr);
    (*env)->ReleaseStringUTFChars (env, jquery_str, cquery_str);
    //(*env)->DeleteLocalRef(env, cip_addr);
    //(*env)->DeleteLocalRef(env, cquery_str);

    fflush(stdout);
    return (rslt_str);
}
#包括
#包括
#包括
#包括“fns_data.h”
#包括“fns_client.h”
#包括“sockRW.h”
#include“/usr/local/include/jni.h”
#包括“JNIiSearchLib.h”
#包括“com_eds_wise_util_JNIiSearchLib.h”
JNIEXPORT jstring JNICALL
Java_com_eds_wise_util_JNIiSearchLib_jniFNSSearchClient(
JNIEnv*env、jobject obj、jstring jip_地址、jint jport_编号、,
jstring jfield、jstring jquery_str、jint jhitnum)
{
HitIds*命中列表=空;
hitListPktStruct*hitPkt=NULL;
int hit_number=0;
int i=0;
int fnsErrno=0;
char*result_str=NULL;
jstring rslt_str=NULL;
常量字符*cip_addr=NULL;
const char*cquery_str=NULL;
char errbuf[1024];
cip_addr=(*env)->GetStringUTFChars(env,jip_addr,0);
if(cip_addr==NULL){
return((*env)->NewStringUTF(env,“错误:无法获取IP地址”);
}
cquery_str=(*env)->GetStringUTFChars(env,jquery_str,0);
if(cquery_str==NULL){
(*环境)->发布StringUTFChars(环境、jip_地址、cip_地址);
//(*env)->DeleteLocalRef(env,cip_addr);
return((*env)->NewStringUTF(env,“错误:无法获取查询字符串”);
}
printf(“[Java\u JNILib\u jniFNSSearchClient]IP地址[%s]端口号[%d]”
“查询器[%s]\n\n”,cip\u地址,jport\u编号,cquery\u str);
/*搜索并获取处理程序和总点击数
*/
点击列表=fns搜索客户端0((字符*)cip地址,jport号码,
“PN”、“char*)cquery_str和hit_number);
fnsErrno=fns_错误_消息();
如果(fnsErrno){
printf(“在fns\u搜索\u client0()\n期间出现错误%d”,fnsErrno);
sprintf(errbuf,“错误:fns\u search\u client0()返回%d.”,fnsErrno);
rslt_str=(*env)->NewStringUTF(env,errbuf);
(*环境)->发布StringUTFChars(环境、jip_地址、cip_地址);
(*env)->ReleaseStringUTFChars(env、jquery\u str、cquery\u str);
//(*env)->DeleteLocalRef(env,cip_addr);
//(*env)->DeleteLocalRef(env,cquery_str);
fflush(stdout);
返回(rslt_str);
}
/*显示总点击数
*/
printf(“总点击次数=%d\n”,点击次数);
/*将处理程序用作参数以检索实际结果
*/
如果(点击次数>0){
fns\u显示ids0((字符*)cip\u地址,jport\u编号,点击列表,
0,命中编号-1和hitPkt);
fnsErrno=fns_错误_消息();
如果(fnsErrno){
printf(“fns\u显示期间出现错误%d\u ids0()\n”,fnsErrno);
sprintf(errbuf,“错误:fns\u display\u ids0()返回%d.”,fnsErrno);
rslt_str=(*env)->NewStringUTF(env,errbuf);
如果(点击列表){
自由字符串(点击列表);
}
(*环境)->发布StringUTFChars(环境、jip_地址、cip_地址);
(*env)->ReleaseStringUTFChars(env、jquery\u str、cquery\u str);
//(*env)->DeleteLocalRef(env,cip_addr);
//(*env)->DeleteLocalRef(env,cquery_str);
fflush(stdout);
返回(rslt_str);
}
}
/*枚举结果列表中的每个项目并显示它们。
*结果以字符串的形式以以下方式返回给Java:
*
*“[hitresult1 | hitresult2 | hitresult3 |..| hitresultN]\0”
*
*其中hitresultN=94字节记录
*
*[+string94+|+string94]+stringTerminator
*/
printf(“malloc[%d]\n”,(命中数*95)+3);
结果_str=malloc((命中数*95)+3)*sizeof(字符));
if(result_str==NULL){
printf(“内存不足,无法malloc\n”);
rslt_str=(*env)->NewStringUTF(env,“错误:内存不足,无法malloc”);
如果(点击列表){
自由字符串(点击列表);
}
如果(hitPkt){
自由列表结构(hitPkt);
}
(*环境)->发布StringUTFChars(环境、jip_地址、cip_地址);
(*env)->ReleaseStringUTFChars(env、jquery\u str、cquery\u str);
//(*env)->DeleteLocalRef(env,cip_addr);
//(*env)->DeleteLocalRef(env,cquery_str);
fflush(stdout);
返回(rslt_str);
}
sprintf(结果“[”);
对于(i=0;i文件名列表[i]);
如果(i!=(点击数字-1)){
strcat(结果为“;”);
}
}
strcat(结果“]”;
printf(“\n\nFNS搜索结果:[来自库]\n”);
printf(“%s\n\n”,result\u str);
/*释放处理程序
*/
如果(点击列表){
自由字符串(点击列表);
}
/*释放结果列表
*/
如果(hitPkt){
自由列表结构(hitPkt);
}
/*为Java做准备
*/
rslt_str=(*env)->NewStringUTF(env,result_str);
/*释放我们的记忆
*/
如果(结果){
自由(结果);
}
(*环境)->发布StringUTFChars(环境、jip_地址、cip_地址);
(*env)->ReleaseStringUTFChars(env、jquery\u str、cquery\u str);
//(*env)->DeleteLocalRef(env,cip_addr);
//(*env)->DeleteLocalRef(env,cquery_str);
fflush(stdout);
返回(rslt_str);
}

debug。使用dmalloc或类似工具查看泄漏的位置。@weili:内存泄漏不会使应用程序崩溃,除非您运行它一段时间并最终耗尽内存。您更有可能两次释放同一块内存,访问了分配区域之外的内存,或者没有正确初始化某些数据结构。@weili:是不是在JNI方法返回后,搜索库保留了传递给fns_display_ids0()的cip_addr?或者