2222import java .util .ArrayList ;
2323import java .util .List ;
2424import java .util .concurrent .atomic .AtomicBoolean ;
25+ import java .util .concurrent .atomic .AtomicInteger ;
2526
2627import io .objectbox .AbstractObjectBoxTest ;
2728
2829
2930import static org .junit .Assert .assertEquals ;
3031import static org .junit .Assert .assertFalse ;
32+ import static org .junit .Assert .assertNotNull ;
3133import static org .junit .Assert .assertThrows ;
3234import static org .junit .Assert .assertTrue ;
3335
@@ -49,18 +51,19 @@ public void exceptionListener_closedStore_works() {
4951 store .setDbExceptionListener (e -> System .out .println ("This is never called" ));
5052 }
5153
52- private static boolean weakRefListenerCalled = false ;
54+ private static AtomicInteger weakRefListenerCalled = new AtomicInteger ( 0 ) ;
5355
5456 @ Test
5557 public void exceptionListener_noLocalRef_works () throws InterruptedException {
58+ weakRefListenerCalled .set (0 );
5659 // Note: do not use lambda, it would keep a reference to this class
5760 // and prevent garbage collection of the listener.
5861 //noinspection Convert2Lambda
5962 DbExceptionListener listenerNoRef = new DbExceptionListener () {
6063 @ Override
6164 public void onDbException (Exception e ) {
6265 System .out .println ("Listener without strong reference is called" );
63- weakRefListenerCalled = true ;
66+ weakRefListenerCalled . incrementAndGet () ;
6467 }
6568 };
6669 WeakReference <DbExceptionListener > weakReference = new WeakReference <>(listenerNoRef );
@@ -70,24 +73,25 @@ public void onDbException(Exception e) {
7073 //noinspection UnusedAssignment
7174 listenerNoRef = null ;
7275
73- // Try and fail to release weak reference .
76+ // Ensure weak reference is kept as JNI is holding on to listener using a "global ref" .
7477 int triesClearWeakRef = 5 ;
7578 while (weakReference .get () != null ) {
7679 if (--triesClearWeakRef == 0 ) break ;
7780 System .out .println ("Suggesting GC" );
7881 System .gc ();
82+ System .runFinalization ();
7983 //noinspection BusyWait
8084 Thread .sleep (300 );
8185 }
8286 assertEquals ("Failed to keep weak reference to listener" , 0 , triesClearWeakRef );
87+ assertNotNull (weakReference .get ());
8388
8489 // Throw, listener should be called.
85- weakRefListenerCalled = false ;
8690 assertThrows (
8791 DbException .class ,
8892 () -> DbExceptionListenerJni .nativeThrowException (store .getNativeStore (), 0 )
8993 );
90- assertTrue ( weakRefListenerCalled );
94+ assertEquals ( 1 , weakRefListenerCalled . get () );
9195
9296 // Remove reference from native side.
9397 store .setDbExceptionListener (null );
@@ -98,18 +102,45 @@ public void onDbException(Exception e) {
98102 if (--triesClearWeakRef == 0 ) break ;
99103 System .out .println ("Suggesting GC" );
100104 System .gc ();
105+ System .runFinalization ();
101106 //noinspection BusyWait
102107 Thread .sleep (300 );
103108 }
104109 assertTrue ("Failed to release weak reference to listener" , triesClearWeakRef > 0 );
105110
106111 // Throw, listener should not be called.
107- weakRefListenerCalled = false ;
108112 assertThrows (
109113 DbException .class ,
110114 () -> DbExceptionListenerJni .nativeThrowException (store .getNativeStore (), 0 )
111115 );
112- assertFalse (weakRefListenerCalled );
116+ assertEquals (1 , weakRefListenerCalled .get ());
117+ }
118+
119+ @ Test
120+ public void exceptionListener_noref () throws InterruptedException {
121+ weakRefListenerCalled .set (0 );
122+
123+ //noinspection Convert2Lambda
124+ store .setDbExceptionListener (new DbExceptionListener () {
125+ @ Override
126+ public void onDbException (Exception e ) {
127+ System .out .println ("Listener without reference is called" );
128+ weakRefListenerCalled .incrementAndGet ();
129+ }
130+ });
131+
132+ for (int i = 0 ; i < 5 ; i ++) {
133+ System .gc ();
134+ System .runFinalization ();
135+ Thread .sleep (100 );
136+ }
137+
138+ // Throw, listener should be called.
139+ assertThrows (
140+ DbException .class ,
141+ () -> DbExceptionListenerJni .nativeThrowException (store .getNativeStore (), 0 )
142+ );
143+ assertEquals (1 , weakRefListenerCalled .get ());
113144 }
114145
115146 @ Test
0 commit comments