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; 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值