Commit ebd1ceb
Remove finalize() methods (1.5)
This is a backport of the PR duckdb#533 to `v1.5-variegata` stable branch.
Problem
-------
In highly parallel environments, creating DuckDBResultSet and
DuckDBPreparedStatement objects causes severe mutex contention on
the global java.lang.ref.Finalizer lock. Profiling with Pyroscope
showed that ~48% of mutex contentions originated from:
DuckDBResultSet.<init>
→ Object.<init>
→ Finalizer.register
→ Finalizer.<init> [GLOBAL LOCK]
When a class overrides finalize(), the JVM registers every new
instance with the Finalizer system using a global lock. In
applications executing many concurrent queries (e.g., using ZIO,
Akka, or thread pools), this single lock becomes a severe
bottleneck, significantly degrading throughput.
Background
----------
The finalize() methods were added in April 2020 (commit 934af9f)
as a safety net to release native JNI resources if users forgot
to call close(). However, finalize() was deprecated in Java 9
(2017) due to:
- Unpredictable execution timing (GC-dependent)
- Performance overhead (extra GC cycles for weak reachability)
- Global lock contention in the Finalizer registration
- Single-threaded Finalizer thread becoming a bottleneck
The modern replacement (java.lang.ref.Cleaner) was introduced in
Java 9, but this driver targets Java 8 compatibility.
Solution
--------
Remove finalize() from all four classes that had it:
- DuckDBConnection
- DuckDBPreparedStatement
- DuckDBResultSet
- DuckDBSingleValueAppender
All these classes already implement AutoCloseable with proper
close() methods. Users should use try-with-resources:
try (Connection conn = DriverManager.getConnection("jdbc:duckdb:");
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
// ...
}
This is standard JDBC best practice and ensures deterministic
resource cleanup without relying on GC finalization.
Impact
------
- Eliminates Finalizer lock contention entirely
- Improves throughput in high-concurrency scenarios
- No behavior change for users who properly close resources
- Users who relied on finalize() for cleanup will now leak
resources if they don't call close() (but finalize() was
never guaranteed to run anyway)1 parent 4a6fab8 commit ebd1ceb
4 files changed
Lines changed: 0 additions & 23 deletions
File tree
- src/main/java/org/duckdb
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | 125 | | |
132 | 126 | | |
133 | 127 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
411 | 411 | | |
412 | 412 | | |
413 | 413 | | |
414 | | - | |
415 | | - | |
416 | | - | |
417 | | - | |
418 | | - | |
419 | | - | |
420 | 414 | | |
421 | 415 | | |
422 | 416 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | 113 | | |
120 | 114 | | |
121 | 115 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | 96 | | |
102 | 97 | | |
103 | 98 | | |
| |||
0 commit comments