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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值