Skip to content

Commit 6c3fe40

Browse files
BoxStore: also print threads where objectbox appears in a class name #258
1 parent 2d93164 commit 6c3fe40

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

objectbox-java/src/main/java/io/objectbox/BoxStore.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ public class BoxStore implements Closeable {
8282

8383
/** The ObjectBox database version this Java library is known to work with. */
8484
private static final String VERSION = "4.3.1-2025-08-02";
85+
86+
private static final String OBJECTBOX_PACKAGE_NAME = "objectbox";
8587
private static BoxStore defaultStore;
8688

8789
/** Currently used DB dirs with values from {@link #getCanonicalPath(File)}. */
@@ -753,28 +755,43 @@ private void checkThreadTermination() {
753755
if (!internalThreadPool().awaitTermination(1, TimeUnit.SECONDS)) {
754756
getErrorOutput().println("ObjectBox thread pool not terminated in time." +
755757
" Ensure all async calls have completed and subscriptions are cancelled before closing the Store." +
756-
"\nPrinting pool threads...");
758+
"\nDumping stack traces of threads on the pool and any using ObjectBox APIs:" +
759+
"\n=== BEGIN OF DUMP ===");
757760
// Note: this may not print any pool threads if other threads are started while enumerating
758761
// (and the pool threads do not make it into the threads array).
759762
Thread[] threads = new Thread[Thread.activeCount()];
760763
int count = Thread.enumerate(threads);
761764
for (int i = 0; i < count; i++) {
762765
Thread thread = threads[i];
763-
if (thread.getName().startsWith(ObjectBoxThreadPool.THREAD_NAME_PREFIX)) {
766+
if (shouldDumpThreadStackTrace(thread)) {
764767
getErrorOutput().println("Thread: " + thread.getName());
765768
StackTraceElement[] trace = thread.getStackTrace();
766769
for (StackTraceElement traceElement : trace) {
767770
getErrorOutput().println("\tat " + traceElement);
768771
}
769772
}
770773
}
771-
getErrorOutput().println("Printing pool threads...DONE");
774+
getErrorOutput().println("=== END OF DUMP ===");
772775
}
773776
} catch (InterruptedException e) {
774777
e.printStackTrace(getErrorOutput());
775778
}
776779
}
777780

781+
private boolean shouldDumpThreadStackTrace(Thread thread) {
782+
// Dump any threads of the internal thread pool
783+
if (thread.getName().startsWith(ObjectBoxThreadPool.THREAD_NAME_PREFIX)) return true;
784+
785+
// Any other thread might be blocking a thread on the internal pool, so also dump any that appear to use
786+
// ObjectBox APIs.
787+
StackTraceElement[] trace = thread.getStackTrace();
788+
for (StackTraceElement traceElement : trace) {
789+
if (traceElement.getClassName().contains(OBJECTBOX_PACKAGE_NAME)) return true;
790+
}
791+
792+
return false;
793+
}
794+
778795
/**
779796
* Danger zone! This will delete all data (files) of this BoxStore!
780797
* You must call {@link #close()} before and read the docs of that method carefully!

tests/objectbox-java-test/src/test/java/io/objectbox/BoxStoreLogTest.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929

3030
import static org.junit.Assert.assertTrue;
31+
import static org.junit.Assert.fail;
3132

3233
/**
3334
* Sets a custom error output stream to assert log messages of {@link BoxStore}.
@@ -65,13 +66,23 @@ public void close_activeThreadPool_printsError() throws UnsupportedEncodingExcep
6566

6667
String errOutput = this.errOutput.toString("UTF-8");
6768
assertTrue(errOutput.contains("ObjectBox thread pool not terminated in time"));
68-
assertTrue(errOutput.contains("Printing pool threads..."));
69-
assertTrue(errOutput.contains("Printing pool threads...DONE"));
70-
// Check that only ObjectBox threads are printed
69+
assertTrue(errOutput.contains("=== BEGIN OF DUMP ==="));
70+
assertTrue(errOutput.contains("=== END OF DUMP ==="));
71+
// Check that only pool threads or threads with stack traces that contain the objectbox package are printed
7172
String[] lines = errOutput.split("\n");
73+
String checkStackTrace = null;
7274
for (String line : lines) {
7375
if (line.startsWith("Thread:")) {
74-
assertTrue("Expected thread name to start with 'ObjectBox-' but was: " + line, line.contains("ObjectBox-"));
76+
if (checkStackTrace != null) {
77+
fail("Expected stack trace to contain class in objectbox package");
78+
}
79+
if (!line.contains("ObjectBox-")) {
80+
checkStackTrace = line;
81+
}
82+
} else if (checkStackTrace != null) {
83+
if (line.contains("objectbox")) {
84+
checkStackTrace = null;
85+
}
7586
}
7687
}
7788
}

0 commit comments

Comments
 (0)