创建JNI封装返回std::shared_ptr的C++方法时类型转换错误如何解决
错误原因
你无法直接将std::shared_ptr实例对象强制转换为jlong类型:std::shared_ptr是栈上分配的智能指针对象,并非原生内存地址,reinterpret_cast不支持这种类型转换。
正确的做法是将std::shared_ptr实例分配到堆内存,把堆内存的指针地址转为jlong传给Java层保存,销毁时再把地址转回std::shared_ptr指针释放即可。
修复代码
1. 修改JNI实现(xxx_fooFactory.cpp)
调整nCreate方法的逻辑,改为在堆上创建std::shared_ptr实例:
JNIEXPORT jlong JNICALL Java_xxx_fooFactory_nCreate (JNIEnv *env, jclass) { JAVA_BINDING_TRY{ auto fooFactory = createFooFactory(); if (fooFactory == nullptr) { throw JavaBindingException(JavaBindingException::kIllegalStateException, "Unable to create foo factory."); } // 堆上创建shared_ptr实例,存储指针 auto* nativeObject = new std::shared_ptr<FooInterface>(fooFactory); return reinterpret_cast<jlong>(nativeObject); } JAVA_BINDING_CATCH(env); return 0; }
nDestroy方法逻辑无需修改,已经符合要求。
2. 修复Java类逻辑错误
你原来的destroyNativeObject方法存在递归调用的问题,会导致运行时栈溢出,修改为调用native的nDestroy方法:
@Override public void destroyNativeObject(long nativeObject) { nDestroy(nativeObject); }
额外注意事项
- 后续如果需要在其他JNI接口中使用Java层传入的
nativeObject,需要先将其转换为std::shared_ptr<FooInterface>*指针,再解引用拿到智能指针实例使用,不要直接强转为FooInterface*裸指针,否则会破坏引用计数规则,导致内存泄漏或者野指针问题 - 确认父类
PlatformInterface的析构逻辑会正确调用destroyNativeObject方法,避免对象销毁时Native层内存泄漏
内容的提问来源于stack exchange,提问作者bourne
相关产品推荐
相关产品推荐

