首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

c++调用java 内存泄露的有关问题

2013-12-13 
c++调用java 内存泄露的问题各位大侠,最近需要用c++调用java,然后自己看了看jni相关的东西,写了下,能运行,

c++调用java 内存泄露的问题
各位大侠,最近需要用c++调用java,然后自己看了看jni相关的东西,写了下,能运行,不过会内存泄露,我检查了下,new了的都delete了,java那边单独测试是不会内存泄露的,大家能不能帮我看看啊

网上看了好多东西,那个IBM有关jni的教程我也看了,说注意要DeleteLocalRef,我也是这样做了,但是就是内存涨的特别厉害,平均5秒就涨1M,我都无语了。各位能不能抽出宝贵的时间帮小弟看看啊,谢过了~~~还有两天就得交程序了~~

#include "cJava.h"
#include <sstream>

extern "C"
using namespace std;

namespace cJava {
ncIdentify::ncIdentify(JavaVM* myncjvm)
{
ncjvm = myncjvm;
JavaVMOption options[2];
  ncenv = NULL;
  JavaVMInitArgs vm_args;
  long status;
  options[0].optionString = "-Djava.compiler=NONE";
  options[1].optionString = "-Djava.class.path=.:../lib/NCnotDep.jar:../lib/CRFPP.jar";
  vm_args.version = JNI_VERSION_1_2; // JDK版本号
  vm_args.nOptions = 2;
  vm_args.options = options;
  status = JNI_CreateJavaVM(&ncjvm, (void**)&ncenv, &vm_args);
  if(status!=JNI_ERR)
  {
  cout<<"createJVM is OK"<<endl;
  }
  else
  {
  cout<<"creatJVM is fail"<<endl;
  }
  nccls = ncenv->FindClass("userinterface/NCidentify");
  cout<<"findClass is OK in c++"<<endl;
  if(nccls !=0){
  // 调用string
  jmethodID mid = ncenv->GetMethodID(nccls,"<init>","()V");
  ncjobj = ncenv->NewObject(nccls,mid);
  jmethodID midload = ncenv->GetMethodID(nccls,"loadResource","()V");
  ncenv->CallObjectMethod(ncjobj,midload);
}
}
ncIdentify::~ncIdentify()
{

ncenv->DeleteLocalRef(ncjobj);
ncenv->DeleteLocalRef(nccls);
ncjvm->DestroyJavaVM();

}
string ncIdentify::getNCresult(string query)
{
  string result;
  jclass strClass = ncenv->FindClass("java/lang/String");
jmethodID ctorID = ncenv->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");

/*char*转jstring*/
jbyteArray bytes = ncenv->NewByteArray(strlen(query.c_str()));
ncenv->SetByteArrayRegion(bytes, 0, strlen(query.c_str()), (jbyte*)query.c_str());
jstring encoding = ncenv->NewStringUTF("gbk");//utf-8
jstring queryJstr = (jstring)ncenv->NewObject(strClass, ctorID, bytes, encoding);
ncenv->DeleteLocalRef(bytes);
  jmethodID ncRegMid= ncenv->GetMethodID(nccls,"runNotDep","(Ljava/lang/String;)Ljava/lang/String;");//这里调用java里的一个函数
  jstring msg = (jstring)ncenv->CallObjectMethod(ncjobj,ncRegMid,queryJstr);
/*jstring转char* */
char* rtn = NULL;

  jmethodID mid = ncenv->GetMethodID(strClass, "getBytes", "(Ljava/lang/String;)[B");

jbyteArray barr =(jbyteArray)ncenv->CallObjectMethod(msg,mid,encoding);

jsize alen =(jsize)ncenv->GetArrayLength(barr);

jbyte* ba = ncenv->GetByteArrayElements(barr,JNI_FALSE);

if(alen > 0){
rtn = (char*)malloc(alen+1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
result = rtn;
free(rtn);
}
ncenv->ReleaseByteArrayElements(barr, ba, 0);
ncenv->DeleteLocalRef(encoding);
ncenv->DeleteLocalRef(strClass);

  ncenv->DeleteLocalRef(msg);
  ncenv->DeleteLocalRef(queryJstr);
  return result;
}
}

int main()
{
ifstream reader;
ofstream writer;

string query = "";
string result = "";
char* javaClassPath = "-Djava.class.path=.:../lib/NCnotDep.jar:../lib/CRFPP.jar";
JavaVM* jvm;

cJava::ncIdentify *myiden = new cJava::ncIdentify(jvm);

string fileInName = "/users/testcJava/0-20";
string fileOutName = "/users/testcJava/answer";
string buffer;
  reader.open(fileInName.c_str());
  writer.open(fileOutName.c_str());
  while(getline(reader,query))
  {
  if(query!="")
  {
  result = myiden->getNCresult(query);
  writer<<result;
  writer<<"\n";
  }
  else
  {
  writer<<"\n";
  }
  }
  reader.close();
  reader.clear();
  writer.close();
  writer.clear();
  delete myiden;
}


[解决办法]
不要做A语言代码修改为B语言代码的无用功。
也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。
只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。
即可很方便地让A、B两种语言之间协调工作。

[解决办法]
可以看看jvm中的global之类的reference是否变化。
楼主在调用java函数的C代码中,需要缓存不会改变的java部分成员函数的handle,不要每次调用都找一次。

热点排行