通过多个jni调用保持某种c++对象的活动性
keep some sort of c++ object alive over multiple jni calls
我的java代码将调用现有的c++代码来解析文件。它将生成一个保存许多数据的对象。我将调用jni的第二个方法来访问这些数据,当我调用第二个方法时,我必须再次解析该文件。这显然是正确的行为。
有办法解决这个问题吗?BTW:我刚接触c++。
我不确定我是否正确理解你的问题。但我想你想做的是在多个jni调用中保持某种c++对象的活力。
你可以做很多事情。首先解析您的文件,并将您的c++对象存储在一个全局变量中。这是最简单的解决方案,但不是一个好的解决方案。
您还可以将c++对象的生命周期转移到java中。
jlong java_some_class_jni_method(...)
{
.... parse your text file ....
MyParseclass* cls = new MyParseclass(...);
....
return (jlong) cls;
}
但是请记住,您需要再次删除这个本机c++类。所以你需要一个jni方法,一定要调用它。
void java_some_calls_jni_method(..., jlong clsPtr)
{
MyParseclass* cls = (MyParseclass*)clsPtr;
... do maybe do something with cls and access the data...
delete cls; // do not use the jlong again in any call
}
BTW:如果你能发布一些代码,那会更有帮助。但我希望这里的伪代码能有所帮助。
这个问题与这个非常相似
以下是我在C++上保持对象活动以便从多个JNI调用引用它们的解决方案:
Java
在Java方面,我正在创建一个带有long
指针的类,以保持对C++对象的引用。将C++方法封装在Java类中,允许我们在多个活动中使用C++方法。请注意,我在构造函数上创建C++对象,在清理时删除该对象。这对于防止内存泄漏非常重要:
public class JavaClass {
// Pointer (using long to account for 64-bit OS)
private long objPtr = 0;
// Create C++ object
public JavaClass() {
createCppObject();
}
// Delete C++ object on cleanup
public void cleanup() {
deleteCppObject();
this.objPtr = 0;
}
// Native methods
public native void createCppObject();
public native void workOnCppObject();
public native void deleteCppObject();
// Load C++ shared library
static {
System.loadLibrary("CppLib");
}
}
C++
在C++方面,我正在定义用于创建、修改和删除对象的函数。值得一提的是,我们必须使用new
和delete
将对象存储在HEAP内存中,以使其在Java类实例的整个生命周期中保持活动。我还使用getFieldId
、SetLongField
和GetLongField
:将指向CppObject
的指针直接存储在JavaClass
中
// Get pointer field straight from `JavaClass`
jfieldID getPtrFieldId(JNIEnv * env, jobject obj)
{
static jfieldID ptrFieldId = 0;
if (!ptrFieldId)
{
jclass c = env->GetObjectClass(obj);
ptrFieldId = env->GetFieldID(c, "objPtr", "J");
env->DeleteLocalRef(c);
}
return ptrFieldId;
}
// Methods to create, modify, and delete Cpp object
extern "C" {
void Java_com_test_jnitest_JavaClass_createCppObject(JNIEnv *env, jobject obj) {
env->SetLongField(obj, getPtrFieldId(env, obj), (jlong) new CppObject);
}
void Java_com_test_jnitest_JavaClass_workOnCppObject(JNIEnv *env, jobject obj) {
CppObject* cppObj = (CppObject*) env->GetLongField(obj, getPtrFieldId(env, obj));
// Write your code to work on CppObject here
}
void Java_com_test_jnitest_JavaClass_deleteCppObject(JNIEnv *env, jobject obj) {
CppObject* cppObj = (CppObject*) env->GetLongField(obj, getPtrFieldId(env, obj));
delete cppObj;
}
}
注意:
- 与Java不同,C++没有垃圾回收,并且对象将驻留在HEAP内存中,直到您使用
delete
为止 - 我使用
GetFieldID
、SetLongField
和GetLongField
来存储C++中的对象引用,但您也可以存储Java中的jlong
对象指针,如其他答案所述 - 在我的最后一段代码中,我将
JavaObject
类实现为Parcelable
,以便将我的类传递给使用Intent
和附加的多个活动
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象