Java 在JNI中保留对本机类对象的引用

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 <

我试图创建一个C++类并将其对象保存到一个数组中,并使用JNI引用java中的C++对象,因为JNI没有提供任何机制来将任何非原始类型的对象保存到java中。 我已经实现了下面提到的代码,但是输出显示我好像已经创建了多个对象,并且在第二次调用创建新的本机对象时,我也收到了一个堆错误

有人能调查一下吗

谢谢

代码:

Java类(用于加载库dll的函数已在LibObj中定义):

C++库代码:

#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();
}