aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/direct_bt/tinyb/DBTNativeDownlink.java14
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx1
-rw-r--r--java/jni/direct_bt/DBTManager.cxx2
-rw-r--r--java/jni/direct_bt/DBTNativeDownlink.cxx22
-rw-r--r--java/jni/direct_bt/helper_dbt.cxx11
-rw-r--r--java/jni/direct_bt/helper_dbt.hpp7
-rw-r--r--src/direct_bt/GATTHandler.cpp2
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() ) {