EXCEPTION_ACCESS_VIOLATION (0xc0000005) Java Jin Dll 问题解决思路

    因为工作需要,研究了一下Java如何调用Dll的方法,最开始设计的接口是直接返回自定义的对象,对象的申请和构造都在jin的实现方法中(即在DLL中申请构造java的自定义对象),结果运行一段时间后,就会出现崩溃情况:




#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x6d898683, pid=1260, tid=6152
#
# Java VM: Java HotSpot(TM) Client VM (11.0-b15 mixed mode windows-x86)
# Problematic frame:
# V  [jvm.dll+0x98683]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x0238d400):  VMThread [stack: 0x020e0000,0x02130000] [id=6152]

siginfo: ExceptionCode=0xc0000005, reading address 0x00000001

Registers:
EAX=0x00000001, EBX=0x08d2d1e8, ECX=0x0212fa10, EDX=0x6d9e0a08
ESP=0x0212f808, EBP=0x0212f868, ESI=0x08d2d1a0, EDI=0x0212fa10
EIP=0x6d898683, EFLAGS=0x00010283

Top of Stack: (sp=0x0212f808)
0x0212f808:   083f6c00 08d2d1a0 6d8b6763 08d2d1a0
0x0212f818:   08d2d190 08d2d1f0 08d2d200 0212f868
0x0212f828:   083f6a70 083f6c04 6d97e2b1 08d2d190
0x0212f838:   0212f868 08d2d000 02307f68 08d2d000
0x0212f848:   08d2d200 6d97e13b 08d2d000 00000080
0x0212f858:   00000061 08d2d200 0212f868 0238d770
0x0212f868:   6d9f802c 02307f68 083e0000 0212fa10
0x0212f878:   6d97e065 08d2d000 00000080 08d2cff8

Instructions: (pc=0x6d898683)
0x6d898673:   24 08 8b 06 85 c0 57 8b f9 74 55 3b 47 1c 73 50
0x6d898683:   8b 08 83 e1 03 80 f9 03 75 1f 8a 0d dd 15 a1 6d


Stack: [0x020e0000,0x02130000],  sp=0x0212f808,  free space=318k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x98683]

.......

后查看了网上的相关资料后发现,这种方式非常不合理,不利于内存空间的管理,极易造成内存释放引发程序崩溃。本着在那里申请在那里释放的原因,处理相关参数,是比较合理的方式。后把程序改成,在jin接口中传入在java中定义的对象,然后在dll中对对象的字段进行赋值操作,这样对象的定义、内存的申请、以及最后的释放,都统一在java中完成,很好地解决的崩溃问题。具体的示例如下:




//java中的类及接口--------------------------------------------------------------------------------------------------------------------------------


package fhcom;

public class Student {
    public int nNumber = 0;
    public int nAge    = 0;
    public String strName = "";
    public String strHome = "";
   
}

public class ZxdcLib {
   
    /*获取一个学生信息*/
    public static native int getStudent(Student student);

    /*获取一组学生信息*/
    public static native int getArrStudent(Student[] arrStudent);

    static{
        System.loadLibrary("JinZxdcLib");
    }
}





//通过调用javac  javah 生成的头文件------------------------------------------------------------------------------

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

#ifndef _Included_fhcom_ZxdcLib
#define _Included_fhcom_ZxdcLib
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     fhcom_ZxdcLib
* Method:    getStudent
* Signature: (Lfhcom/Student;)I
*/
JNIEXPORT jint JNICALL Java_fhcom_ZxdcLib_getStudent
  (JNIEnv *, jclass, jobject);

/*
* Class:     fhcom_ZxdcLib
* Method:    getArrStudent
* Signature: ([Lfhcom/Student;I)I
*/
JNIEXPORT jint JNICALL Java_fhcom_ZxdcLib_getArrStudent
  (JNIEnv *, jclass, jobjectArray);

#ifdef __cplusplus
}
#endif
#endif

//把头文件加入到Dll中,实现其方法----------------------------------------------------





// JinZxdcLib.cpp : Defines the entry point for the DLL application.
//
#include <Windows.h>
#include "stdafx.h"
#include "fhcom_ZxdcLib.h"

#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

//将jstring类型转换成windows类型
char* jstringToWindows( JNIEnv  *env, jstring jstr )
{
    int length = (env)->GetStringLength(jstr );
    const jchar* jcstr = (env)->GetStringChars(jstr, 0 );
    char* rtn = (char*)malloc( length*2+1 );
    int size = 0;
    size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
    if( size <= 0 )
    {
        return NULL;
    }
    (env)->ReleaseStringChars(jstr, jcstr );
    rtn[size] = 0;
    return rtn;
}


//将windows类型转换成jstring类型
jstring WindowsTojstring( JNIEnv* env, const char* str )
{
    jstring rtn = 0;
    int slen = strlen(str);
    unsigned short * buffer = 0;
    if( slen == 0 )
    {
        rtn = (env)->NewStringUTF(str );
    }
    else
    {
        int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
        buffer = (unsigned short *)malloc( length*2 + 1 );
        if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
        {
            rtn = (env)->NewString(  (jchar*)buffer, length );
        }
    }
    if( buffer )
    {
        free( buffer );
    }
    return rtn;
}





/*通过参数传递对象,赋值后返回*/
JNIEXPORT jint JNICALL Java_fhcom_ZxdcLib_getStudent
(JNIEnv *pEnv, jclass cls, jobject obj)
{
    jclass myClass = (pEnv)->FindClass("fhcom/Student");
    if (myClass == NULL)
    {
        return 1;
    }

    jfieldID idNumber = (pEnv)->GetFieldID(myClass, "nNumber", "I");
    jfieldID idAge    = (pEnv)->GetFieldID(myClass, "nAge", "I");
    jfieldID idName   = (pEnv)->GetFieldID(myClass, "strName", "Ljava/lang/String;");
    jfieldID idHome   = (pEnv)->GetFieldID(myClass, "strHome", "Ljava/lang/String;");

    (pEnv)->SetIntField(obj, idNumber, 2001001);
    (pEnv)->SetIntField(obj, idAge, 22);
    (pEnv)->SetObjectField(obj, idName, WindowsTojstring(pEnv, "wang feng"));
    (pEnv)->SetObjectField(obj, idHome, WindowsTojstring(pEnv, "Henan"));
    return 0;
}





/*通过参数传递对象数组(必须初始化),赋值后返回*/
JNIEXPORT jint JNICALL Java_fhcom_ZxdcLib_getArrStudent
(JNIEnv *pEnv, jclass cls, jobjectArray objArr)
{
    jclass myClass = (pEnv)->FindClass("fhcom/Student");
    if (myClass == NULL)
    {
        return 1;
    }

    jint nArrLen = (pEnv)->GetArrayLength(objArr);
    for (int i=0; i<nArrLen; i++)
    {
        jobject objTemp = (pEnv)->GetObjectArrayElement(objArr, i);
        jclass clsTemp  = (pEnv)->GetObjectClass(objTemp);

        jfieldID idNumber = (pEnv)->GetFieldID(clsTemp, "nNumber", "I");
        jfieldID idAge    = (pEnv)->GetFieldID(clsTemp, "nAge", "I");
        jfieldID idName   = (pEnv)->GetFieldID(clsTemp, "strName", "Ljava/lang/String;");
        jfieldID idHome   = (pEnv)->GetFieldID(clsTemp, "strHome", "Ljava/lang/String;");

        (pEnv)->SetIntField(objTemp, idNumber, 2001001+i);
        (pEnv)->SetIntField(objTemp, idAge, 22+i);
        (pEnv)->SetObjectField(objTemp, idName, WindowsTojstring(pEnv, "wang feng"));
        (pEnv)->SetObjectField(objTemp, idHome, WindowsTojstring(pEnv, "Henan"));
    }

    return 0;
}

你可能感兴趣的:(java,jni)