summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2020-06-29 05:59:08 +0200
committerSven Gothel <[email protected]>2020-06-29 05:59:08 +0200
commit0b7e94850a0bb5e4d389709bc9c449cd4f7dc094 (patch)
tree852b5353ac669275145bbb5097692b8ce579df9a
parent809487569a0e521bd9a5850cfbee00c2ee524932 (diff)
Resolve regression calling DBTNativeDownlink.delete() having notifyDeleted() being called back from deleteNativeJavaObject(..)
Regression introduced with commit 83e0c7f75b4206701c1b9c62ebd4282f50f92a31 DBTNativeDownlink.delete() calls DBTNativeDownlink.deleteNativeJavaObject(..), which by itself now calls back using DBTNativeDownlink.notifyDeleted() and purges isValid and nativeInstance. Therefor, DBTNativeDownlink.delete() needs to cache the nativeInstance reference and pass it down to DBTNativeDownlink.deleteImpl(long) as argument. Further refine synchronization, using a local Object and isValid being an AtomicBoolean to allow isValid() return the current state.
-rw-r--r--java/direct_bt/tinyb/DBTAdapter.java2
-rw-r--r--java/direct_bt/tinyb/DBTDevice.java2
-rw-r--r--java/direct_bt/tinyb/DBTGattCharacteristic.java2
-rw-r--r--java/direct_bt/tinyb/DBTGattDescriptor.java2
-rw-r--r--java/direct_bt/tinyb/DBTGattService.java2
-rw-r--r--java/direct_bt/tinyb/DBTManager.java5
-rw-r--r--java/direct_bt/tinyb/DBTNativeDownlink.java68
-rw-r--r--java/jni/direct_bt/DBTAdapter.cxx5
-rw-r--r--java/jni/direct_bt/DBTDevice.cxx5
-rw-r--r--java/jni/direct_bt/DBTGattCharacteristic.cxx5
-rw-r--r--java/jni/direct_bt/DBTGattDescriptor.cxx5
-rw-r--r--java/jni/direct_bt/DBTGattService.cxx5
-rw-r--r--java/jni/direct_bt/DBTManager.cxx5
-rw-r--r--java/jni/direct_bt/DBTNativeDownlink.cxx6
14 files changed, 72 insertions, 47 deletions
diff --git a/java/direct_bt/tinyb/DBTAdapter.java b/java/direct_bt/tinyb/DBTAdapter.java
index 17b975f9..b10eb02c 100644
--- a/java/direct_bt/tinyb/DBTAdapter.java
+++ b/java/direct_bt/tinyb/DBTAdapter.java
@@ -303,7 +303,7 @@ public class DBTAdapter extends DBTObject implements BluetoothAdapter
/* internal */
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
/* discovery */
diff --git a/java/direct_bt/tinyb/DBTDevice.java b/java/direct_bt/tinyb/DBTDevice.java
index 6a0ca25c..8f0b0c4e 100644
--- a/java/direct_bt/tinyb/DBTDevice.java
+++ b/java/direct_bt/tinyb/DBTDevice.java
@@ -597,7 +597,7 @@ public class DBTDevice extends DBTObject implements BluetoothDevice
* </p>
*/
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
@Override
public native boolean addCharacteristicListener(final GATTCharacteristicListener listener, final BluetoothGattCharacteristic characteristicMatch);
diff --git a/java/direct_bt/tinyb/DBTGattCharacteristic.java b/java/direct_bt/tinyb/DBTGattCharacteristic.java
index ccca1ae4..bd7f0dea 100644
--- a/java/direct_bt/tinyb/DBTGattCharacteristic.java
+++ b/java/direct_bt/tinyb/DBTGattCharacteristic.java
@@ -322,6 +322,6 @@ public class DBTGattCharacteristic extends DBTObject implements BluetoothGattCha
private native boolean enableValueNotificationsImpl(boolean v);
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
}
diff --git a/java/direct_bt/tinyb/DBTGattDescriptor.java b/java/direct_bt/tinyb/DBTGattDescriptor.java
index 86b27530..2733f8ba 100644
--- a/java/direct_bt/tinyb/DBTGattDescriptor.java
+++ b/java/direct_bt/tinyb/DBTGattDescriptor.java
@@ -167,5 +167,5 @@ public class DBTGattDescriptor extends DBTObject implements BluetoothGattDescrip
private native boolean writeValueImpl(byte[] argValue) throws BluetoothException;
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
}
diff --git a/java/direct_bt/tinyb/DBTGattService.java b/java/direct_bt/tinyb/DBTGattService.java
index 3bdb45a8..98081e25 100644
--- a/java/direct_bt/tinyb/DBTGattService.java
+++ b/java/direct_bt/tinyb/DBTGattService.java
@@ -131,5 +131,5 @@ public class DBTGattService extends DBTObject implements BluetoothGattService
private native List<BluetoothGattCharacteristic> getCharacteristicsImpl();
@Override
- protected native void deleteImpl();
+ protected native void deleteImpl(long nativeInstance);
}
diff --git a/java/direct_bt/tinyb/DBTManager.java b/java/direct_bt/tinyb/DBTManager.java
index c74f0706..263b7365 100644
--- a/java/direct_bt/tinyb/DBTManager.java
+++ b/java/direct_bt/tinyb/DBTManager.java
@@ -43,6 +43,7 @@ import org.tinyb.BluetoothType;
public class DBTManager implements BluetoothManager
{
protected static final boolean DEBUG = BluetoothFactory.DEBUG;
+ protected static final boolean VERBOSE = BluetoothFactory.VERBOSE;
private static volatile boolean isJVMShuttingDown = false;
private static final List<Runnable> userShutdownHooks = new ArrayList<Runnable>();
@@ -269,7 +270,7 @@ public class DBTManager implements BluetoothManager
private native List<BluetoothAdapter> getAdapterListImpl();
private native void initImpl(final boolean unifyUUID128Bit) throws BluetoothException;
- private native void deleteImpl();
+ private native void deleteImpl(long nativeInstance);
private DBTManager()
{
initImpl(unifyUUID128Bit);
@@ -304,7 +305,7 @@ public class DBTManager implements BluetoothManager
a.close();
}
adapters.clear();
- deleteImpl();
+ deleteImpl(nativeInstance);
}
}
diff --git a/java/direct_bt/tinyb/DBTNativeDownlink.java b/java/direct_bt/tinyb/DBTNativeDownlink.java
index d3535ce0..c45bdb23 100644
--- a/java/direct_bt/tinyb/DBTNativeDownlink.java
+++ b/java/direct_bt/tinyb/DBTNativeDownlink.java
@@ -25,12 +25,15 @@
package direct_bt.tinyb;
+import java.util.concurrent.atomic.AtomicBoolean;
+
import org.tinyb.BluetoothFactory;
public abstract class DBTNativeDownlink
{
- protected long nativeInstance;
- private boolean isValid;
+ private long nativeInstance;
+ private final AtomicBoolean isValid = new AtomicBoolean(false);
+ private final Object nativeLock = new Object();
static {
BluetoothFactory.checkInitialized();
@@ -39,11 +42,11 @@ public abstract class DBTNativeDownlink
protected DBTNativeDownlink(final long nativeInstance)
{
this.nativeInstance = nativeInstance;
- isValid = true;
+ isValid.set(true);
initNativeJavaObject(nativeInstance);
}
- protected final boolean isValid() { return isValid; }
+ protected final boolean isValid() { return isValid.get(); }
@Override
protected void finalize()
@@ -52,41 +55,62 @@ public abstract class DBTNativeDownlink
}
/**
- * Deletes the native instance in the following order
+ * Deletes the {@code nativeInstance} in the following order
* <ol>
- * <li>Removes this java reference from the native instance</li>
- * <li>Deletes the native instance via {@link #deleteImpl()}</li>
- * <li>Sets the nativeInstance := 0</li>
+ * <li>Removes this java reference from the {@code nativeInstance}</li>
+ * <li>Deletes the {@code nativeInstance} via {@link #deleteImpl(long)}</li>
+ * <li>Zeros the {@code nativeInstance} reference</li>
* </ol>
*/
- public synchronized void delete() {
- if (!isValid) {
- return;
+ public final void delete() {
+ synchronized (nativeLock) {
+ if( !isValid.compareAndSet(true, false) ) {
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete: !valid -> bail: "+getClass().getSimpleName());
+ }
+ return;
+ }
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete.0: "+getClass().getSimpleName()+": valid, handle 0x"+Long.toHexString(nativeInstance));
+ }
+ final long _nativeInstance = nativeInstance;
+ nativeInstance = 0;
+ deleteNativeJavaObject(_nativeInstance); // will issue notifyDeleted() itself!
+ deleteImpl(_nativeInstance);
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete.X: "+getClass().getSimpleName()+": handle 0x"+Long.toHexString(nativeInstance));
+ }
}
- isValid = false;
- deleteNativeJavaObject(nativeInstance);
- deleteImpl();
- nativeInstance = 0;
}
/**
* Called from native JavaUplink dtor -> JavaGlobalObj dtor,
* i.e. native instance destructed in native land.
*/
- private synchronized void notifyDeleted() {
- isValid = false;
- nativeInstance = 0;
- // System.err.println("***** notifyDeleted: "+getClass().getSimpleName()+": valid "+isValid+" -> false, handle 0x"+Long.toHexString(nativeInstance)+" -> null: "+toString());
+ private final void notifyDeleted() {
+ synchronized (nativeLock) {
+ final boolean _isValid = isValid.get();
+ final long _nativeInstance = nativeInstance;
+ isValid.set(false);
+ nativeInstance = 0;
+ if( DBTManager.DEBUG ) {
+ System.err.println("JAVA: delete.notifyDeleted: "+getClass().getSimpleName()+", was: valid "+_isValid+", handle 0x"+Long.toHexString(_nativeInstance)+": "+toString());
+ }
+ }
}
/**
* Deletes the native instance.
* <p>
- * Called via {@link #delete()} and at this point this java reference
- * has been removed from the native instance.
+ * Called via {@link #delete()} and at this point
+ * <ul>
+ * <li>this java reference has been removed from the native instance, i.e. {@code JavaUplink}'s {@code javaObjectRef = nullptr}</li>
+ * <li>the {@link #nativeInstance} reference has been zeroed, but passed as argument for this final native deletion task.</li>
+ * </ul>
* </p>
+ * @param nativeInstance copy of {@link #nativeInstance} reference, which has been already zeroed.
*/
- protected abstract void deleteImpl();
+ protected abstract void deleteImpl(long nativeInstance);
private native void initNativeJavaObject(final long nativeInstance);
private native void deleteNativeJavaObject(final long nativeInstance);
diff --git a/java/jni/direct_bt/DBTAdapter.cxx b/java/jni/direct_bt/DBTAdapter.cxx
index 3a8892d6..5adbefbd 100644
--- a/java/jni/direct_bt/DBTAdapter.cxx
+++ b/java/jni/direct_bt/DBTAdapter.cxx
@@ -507,10 +507,11 @@ jstring Java_direct_1bt_tinyb_DBTAdapter_toStringImpl(JNIEnv *env, jobject obj)
return nullptr;
}
-void Java_direct_1bt_tinyb_DBTAdapter_deleteImpl(JNIEnv *env, jobject obj)
+void Java_direct_1bt_tinyb_DBTAdapter_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
{
+ (void)obj;
try {
- DBTAdapter *adapter = getInstance<DBTAdapter>(env, obj);
+ DBTAdapter *adapter = castInstance<DBTAdapter>(nativeInstance);
DBG_PRINT("Java_direct_1bt_tinyb_DBTAdapter_deleteImpl %s", adapter->toString().c_str());
delete adapter;
} catch(...) {
diff --git a/java/jni/direct_bt/DBTDevice.cxx b/java/jni/direct_bt/DBTDevice.cxx
index 55e074cf..e0acb004 100644
--- a/java/jni/direct_bt/DBTDevice.cxx
+++ b/java/jni/direct_bt/DBTDevice.cxx
@@ -246,10 +246,11 @@ jint Java_direct_1bt_tinyb_DBTDevice_removeAllCharacteristicListener(JNIEnv *env
return 0;
}
-void Java_direct_1bt_tinyb_DBTDevice_deleteImpl(JNIEnv *env, jobject obj)
+void Java_direct_1bt_tinyb_DBTDevice_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
{
+ (void)obj;
try {
- DBTDevice *device = getInstance<DBTDevice>(env, obj);
+ DBTDevice *device = castInstance<DBTDevice>(nativeInstance);
device->remove();
// No delete: DBTDevice instance owned by DBTAdapter
// However, device->remove() might issue destruction
diff --git a/java/jni/direct_bt/DBTGattCharacteristic.cxx b/java/jni/direct_bt/DBTGattCharacteristic.cxx
index fb966a93..d7541e2e 100644
--- a/java/jni/direct_bt/DBTGattCharacteristic.cxx
+++ b/java/jni/direct_bt/DBTGattCharacteristic.cxx
@@ -48,9 +48,10 @@ jstring Java_direct_1bt_tinyb_DBTGattCharacteristic_toStringImpl(JNIEnv *env, jo
return nullptr;
}
-void Java_direct_1bt_tinyb_DBTGattCharacteristic_deleteImpl(JNIEnv *env, jobject obj) {
+void Java_direct_1bt_tinyb_DBTGattCharacteristic_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance) {
+ (void)obj;
try {
- GATTCharacteristic *characteristic = getInstance<GATTCharacteristic>(env, obj);
+ GATTCharacteristic *characteristic = castInstance<GATTCharacteristic>(nativeInstance);
(void)characteristic;
// No delete: Service instance owned by GATTService -> DBTDevice
} catch(...) {
diff --git a/java/jni/direct_bt/DBTGattDescriptor.cxx b/java/jni/direct_bt/DBTGattDescriptor.cxx
index 17a1a118..081fda33 100644
--- a/java/jni/direct_bt/DBTGattDescriptor.cxx
+++ b/java/jni/direct_bt/DBTGattDescriptor.cxx
@@ -47,9 +47,10 @@ void Java_direct_1bt_tinyb_DBTGattDescriptor_deleteImpl(JNIEnv *env, jobject obj
}
}
-jstring Java_direct_1bt_tinyb_DBTGattDescriptor_toStringImpl(JNIEnv *env, jobject obj) {
+jstring Java_direct_1bt_tinyb_DBTGattDescriptor_toStringImpl(JNIEnv *env, jobject obj, jlong nativeInstance) {
+ (void)obj;
try {
- GATTDescriptor *nativePtr = getInstance<GATTDescriptor>(env, obj);
+ GATTDescriptor *nativePtr = castInstance<GATTDescriptor>(nativeInstance);
JavaGlobalObj::check(nativePtr->getJavaObject(), E_FILE_LINE);
return from_string_to_jstring(env, nativePtr->toString());
} catch(...) {
diff --git a/java/jni/direct_bt/DBTGattService.cxx b/java/jni/direct_bt/DBTGattService.cxx
index f00f9e2f..fcb234e8 100644
--- a/java/jni/direct_bt/DBTGattService.cxx
+++ b/java/jni/direct_bt/DBTGattService.cxx
@@ -49,9 +49,10 @@ jstring Java_direct_1bt_tinyb_DBTGattService_toStringImpl(JNIEnv *env, jobject o
}
-void Java_direct_1bt_tinyb_DBTGattService_deleteImpl(JNIEnv *env, jobject obj) {
+void Java_direct_1bt_tinyb_DBTGattService_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance) {
+ (void)obj;
try {
- GATTService *service = getInstance<GATTService>(env, obj);
+ GATTService *service = castInstance<GATTService>(nativeInstance);
(void)service;
// No delete: Service instance owned by DBTDevice
} catch(...) {
diff --git a/java/jni/direct_bt/DBTManager.cxx b/java/jni/direct_bt/DBTManager.cxx
index 560a0f92..3a02540f 100644
--- a/java/jni/direct_bt/DBTManager.cxx
+++ b/java/jni/direct_bt/DBTManager.cxx
@@ -53,10 +53,11 @@ void Java_direct_1bt_tinyb_DBTManager_initImpl(JNIEnv *env, jobject obj, jboolea
}
}
-void Java_direct_1bt_tinyb_DBTManager_deleteImpl(JNIEnv *env, jobject obj)
+void Java_direct_1bt_tinyb_DBTManager_deleteImpl(JNIEnv *env, jobject obj, jlong nativeInstance)
{
+ (void)obj;
try {
- DBTManager *manager = getInstance<DBTManager>(env, obj); // special: static singleton
+ DBTManager *manager = castInstance<DBTManager>(nativeInstance); // special: static singleton
manager->close();
manager->setJavaObject(nullptr);
(void) manager;
diff --git a/java/jni/direct_bt/DBTNativeDownlink.cxx b/java/jni/direct_bt/DBTNativeDownlink.cxx
index 77afbd7f..934bf0ca 100644
--- a/java/jni/direct_bt/DBTNativeDownlink.cxx
+++ b/java/jni/direct_bt/DBTNativeDownlink.cxx
@@ -40,9 +40,6 @@ void Java_direct_1bt_tinyb_DBTNativeDownlink_initNativeJavaObject(JNIEnv *env, j
{
try {
JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance);
- 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 ) {
@@ -67,9 +64,6 @@ void Java_direct_1bt_tinyb_DBTNativeDownlink_deleteNativeJavaObject(JNIEnv *env,
(void)obj;
try {
JavaUplink *javaUplink = castInstance<JavaUplink>(nativeInstance);
- 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(...) {