Java 在JNI中保留对本机类对象的引用
我试图创建一个C++类并将其对象保存到一个数组中,并使用JNI引用java中的C++对象,因为JNI没有提供任何机制来将任何非原始类型的对象保存到java中。 我已经实现了下面提到的代码,但是输出显示我好像已经创建了多个对象,并且在第二次调用创建新的本机对象时,我也收到了一个堆错误 有人能调查一下吗 谢谢 代码: Java类(用于加载库dll的函数已在LibObj中定义): C++库代码:Java 在JNI中保留对本机类对象的引用,java,c++,java-native-interface,Java,C++,Java Native Interface,我试图创建一个C++类并将其对象保存到一个数组中,并使用JNI引用java中的C++对象,因为JNI没有提供任何机制来将任何非原始类型的对象保存到java中。 我已经实现了下面提到的代码,但是输出显示我好像已经创建了多个对象,并且在第二次调用创建新的本机对象时,我也收到了一个堆错误 有人能调查一下吗 谢谢 代码: Java类(用于加载库dll的函数已在LibObj中定义): C++库代码: #include "stdafx.h" #include "stdlib.h" #include <
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "org_jnp_pkg004_PureCppObjFactory.h"
class NativeObjClass
{
private:
int num_ran;
int obj_num;
public:
static int obj_cnt;
NativeObjClass()
{
obj_cnt++;
obj_num=obj_cnt;
num_ran=rand();
cout<<"Native Object number "<<setfill('0')<<setw(5)<<obj_cnt<<" Random number:"<<num_ran<<endl;
}
int get_obj_num()
{
return obj_num;
}
int get_num_ran()
{
return num_ran;
}
};
int NativeObjClass::obj_cnt=0;
NativeObjClass *nobj_lst;
long nobj_lst_size=0;
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_newCppObj
(JNIEnv *env, jobject obj)
{
jclass thisCls = env->GetObjectClass(obj);
jfieldID fid=env->GetFieldID(thisCls,"cppobjlstsz","J");
NativeObjClass nobj;
jlong java_lst_sz=env->GetLongField(obj,fid);
NativeObjClass *temp_nobj_lst;
temp_nobj_lst=new NativeObjClass[nobj_lst_size];
if(nobj_lst_size>0)
{
memmove(temp_nobj_lst,nobj_lst,nobj_lst_size);
delete nobj_lst;
}
nobj_lst_size++;
nobj_lst=new NativeObjClass[nobj_lst_size];
if(nobj_lst_size>1)
{
memmove(nobj_lst,temp_nobj_lst,nobj_lst_size);
delete temp_nobj_lst;
}
nobj_lst[nobj_lst_size]=nobj;
java_lst_sz++;
env->SetLongField(obj,fid,java_lst_sz);
}
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_PrintCppObjDetails
(JNIEnv *env, jobject obj, jlong indx)
{
NativeObjClass nobj=nobj_lst[indx];
cout<<"Retrieved Native Object number "<<setfill('0')<<setw(5)<<nobj.get_obj_num()<<" Random number:"<<nobj.get_num_ran()<<endl;
}
输出:
Native Object number 00001 Random number:41
Native Object number 00002 Random number:18467
Retrieved Native Object number 00002 Random number:18467
Native Object number 00003 Random number:6334
Native Object number 00004 Random number:26500
执行此代码后,还会出现堆错误弹出窗口#包括“stdafx.h”
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "org_jnp_pkg004_PureCppObjFactory.h"
class NativeObjClass
{
private:
int num_ran;
int obj_num;
public:
static int obj_cnt;
NativeObjClass()
{
obj_cnt++;
obj_num=obj_cnt;
num_ran=rand();
cout<<"Native Object number "<<setfill('0')<<setw(5)<<obj_cnt<<" Random number:"<<num_ran<<endl;
}
int get_obj_num()
{
return obj_num;
}
int get_num_ran()
{
return num_ran;
}
};
int NativeObjClass::obj_cnt=0;
NativeObjClass *nobj_lst;
long nobj_lst_size=0;
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_newCppObj
(JNIEnv *env, jobject obj)
{
jclass thisCls = env->GetObjectClass(obj);
jfieldID fid=env->GetFieldID(thisCls,"cppobjlstsz","J");
NativeObjClass nobj;
jlong java_lst_sz=env->GetLongField(obj,fid);
if(nobj_lst_size==0)
{
nobj_lst_size++;
nobj_lst=(NativeObjClass*)calloc(nobj_lst_size,sizeof(NativeObjClass));
nobj_lst[nobj_lst_size-1]=nobj;
}
else
{
nobj_lst_size++;
nobj_lst=(NativeObjClass*)realloc(nobj_lst,nobj_lst_size*sizeof(NativeObjClass));
nobj_lst[nobj_lst_size-1]=nobj;
}
java_lst_sz++;
env->SetLongField(obj,fid,java_lst_sz);
}
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_printCppObjDetails
(JNIEnv *env, jobject obj, jlong indx)
{
NativeObjClass nobj=nobj_lst[indx];
cout<<"Retrieved Native Object number "<<setfill('0')<<setw(5)<<nobj.get_obj_num()<<" Random number:"<<nobj.get_num_ran()<<endl;
}
#包括“stdlib.h”
#包括
#包括
#包括
使用名称空间std;
#包括“org_jnp_pkg004_PureCppObjFactory.h”
类NativeObjClass
{
私人:
int num_ran;
int obj_num;
公众:
静态内部对象;
NativeObjClass()
{
obj_cnt++;
obj_num=obj_cnt;
num_ran=rand();
cout好的,下面是一个第一眼看到的问题列表:
使用名称空间std;
格式不好
static int-obj\u cnt;
不是线程安全的
NativeObjClass*nobj_lst;
应为静态成员
NativeObjClass*nobj_lst;
应该是std::vector
long nobj_lst_size=0;
应为静态成员
long nobj\u lst\u size=0;
应为size\t类型
NativeObjClass nobj;
创建一个对象——它不仅仅是一个引用
nobj_lst=(NativeObjClass*)calloc(nobj_lst_size,sizeof(NativeObjClass))
完全是错误的。如果必须使用手动管理的数组,请使用new[]
,但是std::vector
会更好
nobj_lst[nobj_lst_size-1]=nobj
复制您创建的对象
NativeObjClass nobj=nobj_lst[indx];
创建数组对象的无意义副本
请注意,下面的代码还没有经过测试,甚至还没有编译,只是为了展示这个想法
public class CppObject {
private long handle;
public CppObject() {
handle = createNativeObject();
}
public void cleanup() {
deleteNativeObject(handle);
handle = 0;
}
private static native long createNativeObject();
private static native void deleteNativeObject(long handle);
private static native void printObjectDetails(long handle);
public void PrintObjDetails() {
printObjectDetails(handle);
}
}
JNIEXPORT jlong JNICALL whatever_createNativeObject(JNIEnv *env, jobject obj) {
return reinterpret_cast<jlong>(new CppObject());
}
JNIEXPORT void JNICALL whatever_deleteNativeObject(JNIEnv *env, jobject obj, jlong handle) {
delete reinterpret_cast<CppObject *>(handle);
}
JNIEXPORT void JNICALL printObjectDetails(JNIEnv *env, jobject obj, jlong handle) {
reinterpret_cast<CppObject *>(handle)->printDetails();
}
公共类对象{
私人长柄;
公共对象(){
handle=createNativeObject();
}
公共空间清理(){
deleteNativeObject(句柄);
句柄=0;
}
私有静态本机长createNativeObject();
私有静态本机void deleteNativeObject(长句柄);
私有静态本机void printObjectDetails(长句柄);
public void PrintObjDetails(){
printObjectDetails(句柄);
}
}
JNIEXPORT jlong JNICALL which_createNativeObject(JNIEnv*env,jobject obj){
返回reinterpret_cast(新的CppObject());
}
JNIEXPORT void JNICALL which_deleteNativeObject(JNIEnv*env,jobject obj,jlong handle){
删除重新解释(句柄);
}
JNIEXPORT void JNICALL printObjectDetails(JNIEnv*env、jobject对象、jlong句柄){
重新解释强制转换(句柄)->printDetails();
}
一个java长是64位,所以上面的代码在32位和64位平台上都可以工作。< /P> C++代码中有太多的错误,修复这个问题是毫无意义的,我建议在尝试做JNI部分之前学习更多的C++。埃里克,你能告诉我在C++代码中犯的最重要的错误是什么吗?这样我就可以尝试修复它们。如果我在64位和32位窗口上编译相同的代码,应该如何完成本地指针的转换,这会起作用吗?嗨,埃里克,已经把C++代码改成了java。现在它工作得很好。还有其他建议吗?
#include "stdafx.h"
#include "stdlib.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "org_jnp_pkg004_PureCppObjFactory.h"
class NativeObjClass
{
private:
int num_ran;
int obj_num;
public:
static int obj_cnt;
NativeObjClass()
{
obj_cnt++;
obj_num=obj_cnt;
num_ran=rand();
cout<<"Native Object number "<<setfill('0')<<setw(5)<<obj_cnt<<" Random number:"<<num_ran<<endl;
}
int get_obj_num()
{
return obj_num;
}
int get_num_ran()
{
return num_ran;
}
};
int NativeObjClass::obj_cnt=0;
NativeObjClass *nobj_lst;
long nobj_lst_size=0;
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_newCppObj
(JNIEnv *env, jobject obj)
{
jclass thisCls = env->GetObjectClass(obj);
jfieldID fid=env->GetFieldID(thisCls,"cppobjlstsz","J");
NativeObjClass nobj;
jlong java_lst_sz=env->GetLongField(obj,fid);
if(nobj_lst_size==0)
{
nobj_lst_size++;
nobj_lst=(NativeObjClass*)calloc(nobj_lst_size,sizeof(NativeObjClass));
nobj_lst[nobj_lst_size-1]=nobj;
}
else
{
nobj_lst_size++;
nobj_lst=(NativeObjClass*)realloc(nobj_lst,nobj_lst_size*sizeof(NativeObjClass));
nobj_lst[nobj_lst_size-1]=nobj;
}
java_lst_sz++;
env->SetLongField(obj,fid,java_lst_sz);
}
JNIEXPORT void JNICALL Java_org_jnp_pkg004_PureCppObjFactory_printCppObjDetails
(JNIEnv *env, jobject obj, jlong indx)
{
NativeObjClass nobj=nobj_lst[indx];
cout<<"Retrieved Native Object number "<<setfill('0')<<setw(5)<<nobj.get_obj_num()<<" Random number:"<<nobj.get_num_ran()<<endl;
}
public class CppObject {
private long handle;
public CppObject() {
handle = createNativeObject();
}
public void cleanup() {
deleteNativeObject(handle);
handle = 0;
}
private static native long createNativeObject();
private static native void deleteNativeObject(long handle);
private static native void printObjectDetails(long handle);
public void PrintObjDetails() {
printObjectDetails(handle);
}
}
JNIEXPORT jlong JNICALL whatever_createNativeObject(JNIEnv *env, jobject obj) {
return reinterpret_cast<jlong>(new CppObject());
}
JNIEXPORT void JNICALL whatever_deleteNativeObject(JNIEnv *env, jobject obj, jlong handle) {
delete reinterpret_cast<CppObject *>(handle);
}
JNIEXPORT void JNICALL printObjectDetails(JNIEnv *env, jobject obj, jlong handle) {
reinterpret_cast<CppObject *>(handle)->printDetails();
}