diff options
-rw-r--r-- | java/direct_bt/tinyb/DBTNativeDownlink.java | 14 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTDevice.cxx | 1 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTManager.cxx | 2 | ||||
-rw-r--r-- | java/jni/direct_bt/DBTNativeDownlink.cxx | 22 | ||||
-rw-r--r-- | java/jni/direct_bt/helper_dbt.cxx | 11 | ||||
-rw-r--r-- | java/jni/direct_bt/helper_dbt.hpp | 7 | ||||
-rw-r--r-- | src/direct_bt/GATTHandler.cpp | 2 |
7 files changed, 50 insertions, 9 deletions
diff --git a/java/direct_bt/tinyb/DBTNativeDownlink.java b/java/direct_bt/tinyb/DBTNativeDownlink.java index 5e4e3a71..b0b87057 100644 --- a/java/direct_bt/tinyb/DBTNativeDownlink.java +++ b/java/direct_bt/tinyb/DBTNativeDownlink.java @@ -64,12 +64,22 @@ public abstract class DBTNativeDownlink return; } isValid = false; - clearNativeJavaObject(nativeInstance); + deleteNativeJavaObject(nativeInstance); deleteImpl(); nativeInstance = 0; } /** + * Called from native JavaUplink dtor -> JavaGlobalObj dtor, + * i.e. native instance destructed in native land. + */ + private synchronized void notifyDeleted() { + // System.err.println("***** notifyDeleted: "+getClass().getSimpleName()+": valid "+isValid+" -> false, handle 0x"+Long.toHexString(nativeInstance)+" -> null"); + isValid = false; + nativeInstance = 0; + } + + /** * Deletes the native instance. * <p> * Called via {@link #delete()} and at this point this java reference @@ -79,5 +89,5 @@ public abstract class DBTNativeDownlink protected abstract void deleteImpl(); private native void initNativeJavaObject(final long nativeInstance); - private native void clearNativeJavaObject(final long nativeInstance); + private native void deleteNativeJavaObject(final long nativeInstance); } diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx index 958fdba2..0a75b77c 100644 --- a/java/jni/direct_bt/DBTDevice.cxx +++ b/java/jni/direct_bt/DBTDevice.cxx @@ -252,6 +252,7 @@ void Java_direct_1bt_tinyb_DBTDevice_deleteImpl(JNIEnv *env, jobject obj) DBTDevice *device = getInstance<DBTDevice>(env, obj); device->remove(); // No delete: DBTDevice instance owned by DBTAdapter + // However, device->remove() might issue destruction } catch(...) { rethrow_and_raise_java_exception(env); } diff --git a/java/jni/direct_bt/DBTManager.cxx b/java/jni/direct_bt/DBTManager.cxx index 58478f3e..560a0f92 100644 --- a/java/jni/direct_bt/DBTManager.cxx +++ b/java/jni/direct_bt/DBTManager.cxx @@ -45,7 +45,7 @@ void Java_direct_1bt_tinyb_DBTManager_initImpl(JNIEnv *env, jobject obj, jboolea DBTManager *manager = &DBTManager::get(BTMode::BT_MODE_LE); // special: static singleton setInstance<DBTManager>(env, obj, manager); java_exception_check_and_throw(env, E_FILE_LINE); - manager->setJavaObject( std::shared_ptr<JavaAnonObj>( new JavaGlobalObj(obj) ) ); + manager->setJavaObject( std::shared_ptr<JavaAnonObj>( new JavaGlobalObj(obj, nullptr) ) ); JavaGlobalObj::check(manager->getJavaObject(), E_FILE_LINE); DBG_PRINT("Java_direct_1bt_tinyb_DBTManager_init: Manager %s", manager->toString().c_str()); } catch(...) { diff --git a/java/jni/direct_bt/DBTNativeDownlink.cxx b/java/jni/direct_bt/DBTNativeDownlink.cxx index fdfacf5e..77afbd7f 100644 --- a/java/jni/direct_bt/DBTNativeDownlink.cxx +++ b/java/jni/direct_bt/DBTNativeDownlink.cxx @@ -40,7 +40,20 @@ void Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject(JNIEnv *env, j { try { JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance); - std::shared_ptr<JavaGlobalObj> jobjRef( new JavaGlobalObj(obj) ); + if( nullptr == javaUplink ) { + throw InternalError("NativeInstance JavaUplink is NULL", E_FILE_LINE); + } + jclass javaClazz = search_class(env, obj); + java_exception_check_and_throw(env, E_FILE_LINE); + if( nullptr == javaClazz ) { + throw InternalError("DBTNativeDownlink class not found", E_FILE_LINE); + } + jmethodID mNotifyDeleted = search_method(env, javaClazz, "notifyDeleted", "()V", false); + java_exception_check_and_throw(env, E_FILE_LINE); + if( nullptr == mNotifyDeleted ) { + throw InternalError("DBTNativeDownlink class has no notifyDeleted() method, for "+javaUplink->toString(), E_FILE_LINE); + } + std::shared_ptr<JavaGlobalObj> jobjRef( new JavaGlobalObj(obj, mNotifyDeleted) ); javaUplink->setJavaObject( jobjRef ); JavaGlobalObj::check(javaUplink->getJavaObject(), E_FILE_LINE); DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject %p -> %s", javaUplink, javaUplink->toString().c_str()); @@ -49,12 +62,15 @@ void Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject(JNIEnv *env, j } } -void Java_direct_1bt_tinyb_DBTNativeDownlink_clearNativeJavaObject(JNIEnv *env, jobject obj, jlong nativeInstance) +void Java_direct_1bt_tinyb_DBTNativeDownlink_deleteNativeJavaObject(JNIEnv *env, jobject obj, jlong nativeInstance) { (void)obj; try { JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance); - DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_clearNativeJavaObject %p -> %s", javaUplink, javaUplink->toString().c_str()); + if( nullptr == javaUplink ) { + throw InternalError("NativeInstance JavaUplink is NULL", E_FILE_LINE); + } + DBG_PRINT("Java_direct_1bt_tinyb_DBTNativeDownlink_deleteNativeJavaObject %p -> %s", javaUplink, javaUplink->toString().c_str()); javaUplink->setJavaObject(nullptr); } catch(...) { rethrow_and_raise_java_exception(env); diff --git a/java/jni/direct_bt/helper_dbt.cxx b/java/jni/direct_bt/helper_dbt.cxx index b1690edf..7c0920db 100644 --- a/java/jni/direct_bt/helper_dbt.cxx +++ b/java/jni/direct_bt/helper_dbt.cxx @@ -67,3 +67,14 @@ jstring direct_bt::fromBDAddressTypeToJavaAddressType(JNIEnv *env, BDAddressType return from_string_to_jstring(env, jStringEmpty); } } + +JavaGlobalObj::~JavaGlobalObj() { + jobject obj = javaObjectRef.getObject(); + if( nullptr == obj || nullptr == mNotifyDeleted ) { + return; + } + JNIEnv *env = *jni_env; + env->CallVoidMethod(obj, mNotifyDeleted); + java_exception_check_and_throw(env, E_FILE_LINE); +} + diff --git a/java/jni/direct_bt/helper_dbt.hpp b/java/jni/direct_bt/helper_dbt.hpp index 40e2c609..d71104e7 100644 --- a/java/jni/direct_bt/helper_dbt.hpp +++ b/java/jni/direct_bt/helper_dbt.hpp @@ -59,6 +59,7 @@ namespace direct_bt { class JavaGlobalObj : public JavaAnonObj { private: JNIGlobalRef javaObjectRef; + jmethodID mNotifyDeleted; public: static inline void check(const std::shared_ptr<JavaAnonObj> & shref, const char* file, int line) { @@ -80,13 +81,16 @@ namespace direct_bt { } return true; } - JavaGlobalObj(jobject obj) : javaObjectRef(obj) { } + JavaGlobalObj(jobject obj, jmethodID mNotifyDeleted) + : javaObjectRef(obj), mNotifyDeleted(mNotifyDeleted) { } JavaGlobalObj(const JavaGlobalObj &o) noexcept = default; JavaGlobalObj(JavaGlobalObj &&o) noexcept = default; JavaGlobalObj& operator=(const JavaGlobalObj &o) noexcept = default; JavaGlobalObj& operator=(JavaGlobalObj &&o) noexcept = default; + virtual ~JavaGlobalObj(); + std::string toString() const override { const uint64_t ref = (uint64_t)(void*)javaObjectRef.getObject(); return "JavaGlobalObj["+uint64HexString(ref, true)+"]"; @@ -113,7 +117,6 @@ namespace direct_bt { } }; - jclass search_class(JNIEnv *env, JavaUplink &object); template <typename T> diff --git a/src/direct_bt/GATTHandler.cpp b/src/direct_bt/GATTHandler.cpp index 3252deb2..2eb45f7c 100644 --- a/src/direct_bt/GATTHandler.cpp +++ b/src/direct_bt/GATTHandler.cpp @@ -267,7 +267,7 @@ bool GATTHandler::connect() { return true; } hasIOError = false; - INFO_PRINT("GATTHandler::connect: Start: GattHandler[%s], l2cap[%s]: %s", + DBG_PRINT("GATTHandler::connect: Start: GattHandler[%s], l2cap[%s]: %s", getStateString().c_str(), l2cap.getStateString().c_str(), deviceString.c_str()); if( !l2cap.connect() || !validateConnected() ) { |