版主帮我看一下,是否是java的漏洞?
class staMeter{
public int iGross;
public double ratedLoad;
public double DeviationValue_plus;
public double DeviationValue_negative;
public double MeterPrecision;
public int iMeterStatusvalue;
public int iMeterStatusStability;
}
class testdll
{
static
{
System.loadLibrary("javachimeitx");//载入静态库,test函数在其中实现
}
private native int OpenComPort(int iCom,int iBaudRate); //声明本地调用
private native int CloseComPort(int hd); private native staMeter ReadDataRM(int hd);
public int java_OpenComPort(int iCom,int iBaudRate)
{
return OpenComPort(iCom,iBaudRate);
}
public int java_CloseComPort(int hd)
{
return CloseComPort(hd);
}
public staMeter java_ReadDataRM(int hd)
{
return ReadDataRM(hd);
}
public static void main(String args[])
{
testdll td = new testdll();
int hd=td.java_OpenComPort(1,19200);
staMeter pstateMeter=new staMeter();
for(int i=0;i<30000*10000;i++)
{
try
{
pstateMeter=td.java_ReadDataRM(hd);
System.out.println(i);
//加 System.out.println(i);一段时间后就会出错,
//不加就没有问题。不会是DLL的问题吧。但不加就没有问题啊
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
System.out.println("pstateMeter=td.java_ReadDataRM(hd) 3000*10000s OK ");
td.java_CloseComPort(hd);
}
}
问题点数:100、回复次数:26Top
1 楼healer_kx(甘草(楼主揭贴吧,我们这些上班灌水的也不容易))回复于 2006-08-18 14:40:04 得分 5
很可能出现问题啊,。
Top
2 楼OnlyFor_love(『勾勾手指头 一辈子不分手』)回复于 2006-08-18 14:41:25 得分 5
对调用dll不太熟悉 关注一下Top
3 楼treeroot(旗鲁特)回复于 2006-08-18 14:48:30 得分 5
和dll没关系呀
System.out.println(i);这句代码和其他的代码没有关系呀Top
4 楼robin_wan(爱你没商量)回复于 2006-08-18 14:53:12 得分 0
to healer_kx(甘草(朝圣中... ...)) :
哪里有可能有问题啊?
(1)是指system.out.println(i);有问题还是DLL中的td.java_ReadDataRM(hd)有问题。
(2)若DLL中的td.java_ReadDataRM(hd)有问题不什么当没有system.out.println(i)这一行的时候程序就不会出错,且能正确执行??????
to treeroot(旗鲁特) :
但是就是加了这一句后就出问题,我也不知是啥原因?
Top
5 楼jihanzhong(逍遥)回复于 2006-08-18 15:08:09 得分 0
先把错误信息贴出来看看Top
6 楼robin_wan(爱你没商量)回复于 2006-08-18 16:58:48 得分 0
当加了system.out.println(i)后一段时间,一般在i=5xx,或i=19xx时就报异常。不加则没不会出现。
# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00aeda1c, pid=1736, tid=2956
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_07-b03 mixed mode, sharing)
# Problematic frame:
# j testdll.main([Ljava/lang/String;)V+342
#
# An error report file with more information is saved as hs_err_pid1736.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
Top
7 楼robin_wan(爱你没商量)回复于 2006-08-18 17:05:16 得分 0
DLL为C++所写,调用了5百多次后出现异常。
(1)应该不会是DLL的问题吧。否则一次出会出错啊。
(2)假设是DLL的问题,哪为什么在java中调用后,只要不加system.out.prinln(i)就不会有问题啊?
(3)在pstateMeter=td.java_ReadDataRM(hd);执行后使用其返回的对象也不会有问题,
是否更加说明了DLL没有问题???如下不会出错:
pstateMeter=td.java_ReadDataRM(hd);
int int1=pstateMeter.iGross;
int int2=pstateMeter。iMeterStatusvalue;
Top
8 楼terry_yip(我只回答引起我思考的问题)回复于 2006-08-18 17:21:51 得分 5
楼主说出问题,请问报错语句是什么?
(1)应该不会是DLL的问题吧。否则一次出会出错啊。
这应该是dll中的内存地址操作有关系吧,你查一下DLL里面有指针的操作,又或者看看是不是什么资源没释放,再退一步,你用C++来调用这个dll一千次看看有没有错,就知道是不是JAVA的问题了。
(2)假设是DLL的问题,哪为什么在java中调用后,只要不加system.out.prinln(i)就不会有问题啊?
这个说法没什么逻辑,你再确认看看是不是真的是这样。Top
9 楼maquan('ma:kju)回复于 2006-08-18 17:30:42 得分 5
奇怪,有趣,我也想知道答案。mark 一下~~Top
10 楼robin_wan(爱你没商量)回复于 2006-08-19 11:05:32 得分 0
to terry_yip:
(1)C++应该没有办法再调用这个DLL了。
(2)"这个说法没什么逻辑,你再确认看看是不是真的是这样"
真的是这样,不加printlnr执行3000*10000次都不会出错。
Top
11 楼robin_wan(爱你没商量)回复于 2006-08-19 14:49:04 得分 0
有人知道吗?版主帮帮忙吧!Top
12 楼robin_wan(爱你没商量)回复于 2006-08-20 12:19:50 得分 0
版主帮帮忙吧!
我是用C++的。主要是客户(用java的)要用到C++的DLL,
所以我就写了一个通讯方面的DLL,用的是JNI方式。
java我不熟,因此请各位多多发言了!!!!!Top
13 楼crazycy(崔毅,blog:http://www.blogjava.net/crazycy/)回复于 2006-08-20 12:58:49 得分 5
for(int i=0;i<30000*10000;i++)
{
try
{
pstateMeter=td.java_ReadDataRM(hd);
System.out.println(i);
//加 System.out.println(i);一段时间后就会出错,
===================================
初步怀疑这个i是否超过了int定义的范围呢?!
同时,jni调用处没有错误;Top
14 楼crazycy(崔毅,blog:http://www.blogjava.net/crazycy/)回复于 2006-08-20 12:59:45 得分 5
楼主,你这样来,你看看i打印出的最大值是多少?
具体的错误信息?
都贴出来看看Top
15 楼robin_wan(爱你没商量)回复于 2006-08-21 09:14:15 得分 0
不是这样的,当i(max)=3000时也会出错。出错时i一般等于5百多,或19XX,一直都在此区间
内有错。
如下也会有错:
for(int i=0;i<3000;i++)
{
try
{
pstateMeter=td.java_ReadDataRM(hd);
System.out.println(i);
//加 System.out.println(i);一段时间后就会出错,
}
}
Top
16 楼robin_wan(爱你没商量)回复于 2006-08-21 09:23:59 得分 0
怀疑是C++中资源没有释放造成,现贴上C++ DLL的代码:
(1)原本在其中加上了try{}catch(){},但是也不能捕捉到异常。
(2)怀疑jfieldID等部分资料没有释放,但是如果没有释放的话java中不加system.out.print(i)也应该有错啊。
(3)怀疑jfieldID等部分资料没有释放,但是怎样释放呢?加 if(ival_Gross )delete ival_Gross ;反而C++中有异常。不加c++正常。
JNIEXPORT jobject JNICALL Java_testdll_ReadDataRM
(JNIEnv *jenv, jobject jobj, jint hd){
char *ptr;
int j;
int RetryNum;
char back[280+20];
char cmdstr[10];
staMeter pstaMeter;
//INIT
pstaMeter.iGross=10;
pstaMeter.iMeterStatusvalue=0;
pstaMeter.iMeterStatusStability=0;
pstaMeter.ratedLoad=80000.0;
pstaMeter.DeviationValue_plus=0;
pstaMeter.DeviationValue_negative=0;
pstaMeter.MeterPrecision=0;
//获取Java中的实例类
jclass objectClass = (jenv)->FindClass("staMeter");
if(objectClass)
{
jfieldID ival_Gross = (jenv)->GetFieldID(objectClass,"iGross","I");
jfieldID ival_MeterStatusvalue = (jenv)->GetFieldID(objectClass,"iMeterStatusvalue","I");
jfieldID ival_MeterStatusStability = (jenv)->GetFieldID(objectClass,"iMeterStatusStability","I");
jfieldID dval_ratedLoad = (jenv)->GetFieldID(objectClass,"ratedLoad","D");
jfieldID dval_DeviationValue_plus = (jenv)->GetFieldID(objectClass,"DeviationValue_plus","D");
jfieldID dval_DeviationValue_negative = (jenv)->GetFieldID(objectClass,"DeviationValue_negative","D");
jfieldID dval_MeterPrecision = (jenv)->GetFieldID(objectClass,"MeterPrecision","D");
(jenv)->SetIntField(jobj,ival_Gross,pstaMeter.iGross);
(jenv)->SetIntField(jobj,ival_MeterStatusvalue,pstaMeter.iMeterStatusvalue);
(jenv)->SetIntField(jobj,ival_MeterStatusStability,pstaMeter.iMeterStatusStability);
(jenv)->SetDoubleField(jobj,dval_ratedLoad,pstaMeter.ratedLoad);
(jenv)->SetDoubleField(jobj,dval_DeviationValue_plus,pstaMeter.DeviationValue_plus);
(jenv)->SetDoubleField(jobj,dval_DeviationValue_negative,pstaMeter.DeviationValue_negative);
(jenv)->SetDoubleField(jobj,dval_MeterPrecision,pstaMeter.MeterPrecision);
return jobj;
}
else
{
return NULL;
}
}
Top
17 楼zhmt(孜风)回复于 2006-08-21 09:27:29 得分 5
路过,友情up!Top
18 楼wmzsl(王明哲)回复于 2006-08-21 09:32:03 得分 0
都什么和什么啊呵呵Top
19 楼bigc2000(公元2005年4月9日)回复于 2006-08-21 10:24:52 得分 30
这种异常,肯定是C++部分,想都不用想,
hs_err_pid1736.log
请把这个文件贴出来看看。
还有,下次看到EXCEPTION_ACCESS_VIOLATION(0xc0000005)
这个时候,就可以断定是Native api非法的内存访问。 (java的虚拟机已经十分完美了,不用你怀疑)
我是菜鸟,只知道这几种最有可能非法访问导致上面错误(堆栈益处,映射文件数据溢出,野指针修改的数据破坏了java上层的数据)。
你上面的情况,可能就是第一种资源不释放或者多次释放同一个指针。
看你的代码,(由于不全)好像你每次返回的都是同一个对象return jobj;也就是掉用者。
pstateMeter,td下面怎么使用的?
还有就是,你这个就是简单的clone,干吗要整个如此麻烦的jni 函数?
Top
20 楼maquan('ma:kju)回复于 2006-08-21 11:00:24 得分 10
看看你的 C++ 程序的 calling convention 是不是跟 JNI 要求的一致。
虽然我觉得这个环节出错的可能性不大(毕竟 .h 是 javah 生成的嘛),不过还是确认一下为好。我总觉得从现象上看好像跟这个有点关系。Top
21 楼robin_wan(爱你没商量)回复于 2006-08-21 15:38:05 得分 0
to bigc2000(公元2005年4月9日):
(1)代码已经很全了。Java_testdll_ReadDataRM()主要是读外设然后反回相关的信息。
(2)“还有就是,你这个就是简单的clone,干吗要整个如此麻烦的jni 函数?”
当然不会如此简单了。
do_something(); 真正使用的时侯,这里要加上读仪表的处理。现在没有加也会有错。
//获取Java中的实例类
jclass objectClass = (jenv)->FindClass("staMeter");
(3)java中为何不加system.out.print(i);就不会有错。C++部分还是同样调用过了,????Top
22 楼robin_wan(爱你没商量)回复于 2006-08-21 16:40:24 得分 0
初步找到问题,主要是如下语句有问题:
(jenv)->SetIntField(jobj,ival_Gross,pstaMeter.iGross);
(jenv)->SetIntField(jobj,ival_MeterStatusvalue,pstaMeter.iMeterStatusvalue);
(jenv)->SetIntField(jobj,ival_MeterStatusStability,pstaMeter.iMeterStatusStability);
(jenv)->SetDoubleField(jobj,dval_ratedLoad,pstaMeter.ratedLoad);
(jenv)->SetDoubleField(jobj,dval_DeviationValue_plus,pstaMeter.DeviationValue_plus);
(jenv)->SetDoubleField(jobj,dval_DeviationValue_negative,pstaMeter.DeviationValue_negative);
(jenv)->SetDoubleField(jobj,dval_MeterPrecision,pstaMeter.MeterPrecision);
将其改为一条语句都出错如原样,也将pstaMeter.iMeterStatusvalue直接用10代替
也都一样。齐怪了?????
jenv->SetIntField(jobj,ival_Gross,10);
Top
23 楼maquan('ma:kju)回复于 2006-08-21 17:34:30 得分 5
> An error report file with more information is saved as hs_err_pid1736.log
楼主检查过 hs_err_pid1736.log 这个文件吗?有什么发现吗?
能不能帖出来让大家看看~~Top
24 楼bigc2000(公元2005年4月9日)回复于 2006-08-21 22:48:51 得分 0
To : robin_wan (爱你没商量)
我已经说了,你怎么每次都返回同一个jobj,也就是说,如果在java端没有
pstateMeter=td.java_ReadDataRM(hd);
这句调用者是td,可是C++返回的也是td对象本身,所以相当于 pstateMeter = td;
jclass objectClass = (jenv)->FindClass("staMeter");
这个是查找class,而不是对象实例,也就是查找已经被加载且已定义的一个class而已;
jobj是实例,而不是表示类。Top
25 楼robin_wan(爱你没商量)回复于 2006-08-22 09:28:31 得分 0
To bigc2000(公元2005年4月9日):
非常感激你及上楼上各位的发言!
还有如下疑问:
(一)“pstateMeter=td.java_ReadDataRM(hd);这句调用者是td,可是C++返回的也是td对象本身,所以相当于 pstateMeter = td;”
<Ⅰ>不对呀,java中原型是public staMeter java_ReadDataRM(int hd)返回的是类staMeter的引用。C++中实际上是给这个类的各个属性赋值。
<Ⅱ>因为C++生成的DLL无法知道调用者(java程序)生成的是
pstateMeter (语句staMeter pstateMeter=new staMeter();)
因此C++中只能用:
JNIEXPORT jobject JNICALL Java_testdll_ReadDataRM
(JNIEnv *jenv, jobject jobj, jint hd)
{
注:java中Java_testdll_ReadDataRM()应该返回staMeter
用javah testdll 后生成的原型只能返回的是jobject。
//用下句获取Java中的实例类。
jclass objectClass = (jenv)->FindClass("staMeter");
//用下句获取Java中的实例类的一个名iGross的Field。
jfieldID ival_Gross= (jenv)->GetFieldID(objectClass,"iGross","I");
//用下句给实例类的一个名iGross的Field赋值。
(jenv)->SetIntField(jobj,ival_Gross,pstaMeter.iGross);
//用下句返回实例类的指针
return jobj;
}
(二)如果我的理解有误,哪象我这样的需求(返回一个类的引用,C++中实际就是返回一个结构体类型),到底要怎样写才能实现呢。
Top
26 楼bigc2000(公元2005年4月9日)回复于 2006-08-23 20:46:44 得分 15
java_ReadDataRM
将该函数修改下增加一个参数
public void java_ReadDataRM(staMeter pstateMeter,int hd)
{
return ReadDataRM(pstateMeter,hd);
}
相应C++部分就不用return了。
C++部分JNIEXPORT jobject JNICALL Java_testdll_ReadDataRM
(JNIEnv *env, jobject jobj, jobject pStaMeter, jint hd)
第一个jobj相当于this,第二个个开始才是参数。
要不按你说的就这样,在c++部分分配,
实在看不懂你说的。 这句话--- 注:java中Java_testdll_ReadDataRM()应该返回staMeter
用javah testdll 后生成的原型只能返回的是jobject。
FindClas是查找类(也就是类的说明,而不是实例)第一个jobj才是是类,它就是td。
好了不说了。Top




