From b29cbe58d405582d7669afe4ce107d15ec74f7c4 Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 19:06:06 +0530 Subject: [PATCH 1/9] Add JdbcResourceLeak tests for JDBC resource management This file contains tests for JDBC resource leak detection, including various scenarios for ResultSet, Statement, and PreparedStatement resource management. --- .../tests/resourceleak/JdbcResourceLeak.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 checker/tests/resourceleak/JdbcResourceLeak.java diff --git a/checker/tests/resourceleak/JdbcResourceLeak.java b/checker/tests/resourceleak/JdbcResourceLeak.java new file mode 100644 index 000000000000..26e7389119a2 --- /dev/null +++ b/checker/tests/resourceleak/JdbcResourceLeak.java @@ -0,0 +1,60 @@ +// Tests for JDBC types resource leak detection +// Test case for issue 6354: +// https://github.com/typetools/checker-framework/issues/6354 + +import java.sql.*; + +class JdbcResourceLeak { + + // ========== ResultSet Tests ========== + + void resultSetNotClosed(Statement stmt) throws SQLException { + ResultSet rs = stmt.executeQuery("SELECT 1"); + // :: error: (required.method.not.called) + } + + void resultSetClosed(Statement stmt) throws SQLException { + ResultSet rs = stmt.executeQuery("SELECT 1"); + rs.close(); + } + + // ========== Statement Tests ========== + + void statementNotClosed(Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + // :: error: (required.method.not.called) + } + + void statementClosed(Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + stmt.close(); + } + + // ========== PreparedStatement Tests ========== + + void preparedStatementNotClosed(Connection conn) throws SQLException { + PreparedStatement ps = conn.prepareStatement("SELECT ?"); + // :: error: (required.method.not.called) + } + + void preparedStatementClosed(Connection conn) throws SQLException { + PreparedStatement ps = conn.prepareStatement("SELECT ?"); + ps.close(); + } + + // ========== Nested Resources ========== + + void nestedBothClosed(Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT 1"); + rs.close(); + stmt.close(); + } + + void nestedStatementNotClosed(Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + // :: error: (required.method.not.called) + ResultSet rs = stmt.executeQuery("SELECT 1"); + rs.close(); + } +} From 68905acca8a06bf4b0a15667c5a94e6e44034fdb Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 19:06:47 +0530 Subject: [PATCH 2/9] Add resource leak detection tests for RowSet types Added tests for resource leak detection in various RowSet types, including JdbcRowSet, CachedRowSet, FilteredRowSet, WebRowSet, and JoinRowSet. --- .../resourceleak/RowSetResourceLeak.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 checker/tests/resourceleak/RowSetResourceLeak.java diff --git a/checker/tests/resourceleak/RowSetResourceLeak.java b/checker/tests/resourceleak/RowSetResourceLeak.java new file mode 100644 index 000000000000..223c2c7294b9 --- /dev/null +++ b/checker/tests/resourceleak/RowSetResourceLeak.java @@ -0,0 +1,84 @@ +// Tests for RowSet types resource leak detection +// Test case for issue 6354: +// https://github.com/typetools/checker-framework/issues/6354 + +import javax.sql.rowset.*; +import com.sun.rowset.*; +import java.sql.*; + +class RowSetResourceLeak { + + // ========== JdbcRowSet Tests ========== + + void jdbcRowSetNotClosed(ResultSet rs) throws SQLException { + JdbcRowSet jrs = new JdbcRowSetImpl(rs); + // :: error: (required.method.not.called) + } + + void jdbcRowSetClosed(ResultSet rs) throws SQLException { + JdbcRowSet jrs = new JdbcRowSetImpl(rs); + jrs.close(); + } + + // ========== CachedRowSet Tests ========== + + void cachedRowSetNotClosed() throws SQLException { + CachedRowSet crs = new CachedRowSetImpl(); + // :: error: (required.method.not.called) + } + + void cachedRowSetClosed() throws SQLException { + CachedRowSet crs = new CachedRowSetImpl(); + crs.close(); + } + + void cachedRowSetToResultSetNotClosed() throws SQLException { + CachedRowSet crs = new CachedRowSetImpl(); + ResultSet rs = crs.toResultSet(); + // :: error: (required.method.not.called) + crs.close(); + } + + void cachedRowSetToResultSetBothClosed() throws SQLException { + CachedRowSet crs = new CachedRowSetImpl(); + ResultSet rs = crs.toResultSet(); + rs.close(); + crs.close(); + } + + // ========== FilteredRowSet Tests ========== + + void filteredRowSetNotClosed() throws SQLException { + FilteredRowSet frs = new FilteredRowSetImpl(); + // :: error: (required.method.not.called) + } + + void filteredRowSetClosed() throws SQLException { + FilteredRowSet frs = new FilteredRowSetImpl(); + frs.close(); + } + + // ========== WebRowSet Tests ========== + + void webRowSetNotClosed() throws SQLException { + WebRowSet wrs = new WebRowSetImpl(); + // :: error: (required.method.not.called) + } + + void webRowSetClosed() throws SQLException { + WebRowSet wrs = new WebRowSetImpl(); + wrs.close(); + } + + // ========== JoinRowSet Tests ========== + + void joinRowSetNotClosed() throws SQLException { + JoinRowSet jrs = new JoinRowSetImpl(); + // :: error: (required.method.not.called) + } + + void joinRowSetClosed() throws SQLException { + JoinRowSet jrs = new JoinRowSetImpl(); + jrs.close(); + } +} From 5ca2cf891afb85ecf1144c46d9ba8c5185282fc3 Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 19:31:21 +0530 Subject: [PATCH 3/9] Test: fix misplaced error annotations in JDBC resource leak tests --- checker/tests/resourceleak/JdbcResourceLeak.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/tests/resourceleak/JdbcResourceLeak.java b/checker/tests/resourceleak/JdbcResourceLeak.java index 26e7389119a2..b32d3db158a4 100644 --- a/checker/tests/resourceleak/JdbcResourceLeak.java +++ b/checker/tests/resourceleak/JdbcResourceLeak.java @@ -53,8 +53,8 @@ void nestedBothClosed(Connection conn) throws SQLException { void nestedStatementNotClosed(Connection conn) throws SQLException { Statement stmt = conn.createStatement(); - // :: error: (required.method.not.called) ResultSet rs = stmt.executeQuery("SELECT 1"); rs.close(); + // :: error: (required.method.not.called) } } From 9d2816ecbb9d1fa247191b21a85d37c7b964e143 Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 19:33:12 +0530 Subject: [PATCH 4/9] Test: fix misplaced error annotations in JDBC resource leak tests --- checker/tests/resourceleak/RowSetResourceLeak.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/tests/resourceleak/RowSetResourceLeak.java b/checker/tests/resourceleak/RowSetResourceLeak.java index 223c2c7294b9..3ce9c692ab09 100644 --- a/checker/tests/resourceleak/RowSetResourceLeak.java +++ b/checker/tests/resourceleak/RowSetResourceLeak.java @@ -35,8 +35,8 @@ void cachedRowSetClosed() throws SQLException { void cachedRowSetToResultSetNotClosed() throws SQLException { CachedRowSet crs = new CachedRowSetImpl(); ResultSet rs = crs.toResultSet(); - // :: error: (required.method.not.called) crs.close(); + // :: error: (required.method.not.called) } void cachedRowSetToResultSetBothClosed() throws SQLException { From 76273bd93170464f1040c433bc4e7102c1616c55 Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 22:51:47 +0530 Subject: [PATCH 5/9] Test: add nested ResultSet leak scenario --- checker/tests/resourceleak/JdbcResourceLeak.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/checker/tests/resourceleak/JdbcResourceLeak.java b/checker/tests/resourceleak/JdbcResourceLeak.java index b32d3db158a4..5327f4df35ab 100644 --- a/checker/tests/resourceleak/JdbcResourceLeak.java +++ b/checker/tests/resourceleak/JdbcResourceLeak.java @@ -55,6 +55,14 @@ void nestedStatementNotClosed(Connection conn) throws SQLException { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT 1"); rs.close(); - // :: error: (required.method.not.called) + // :: error: (required.method.not.called) + } + + void nestedResultSetNotClosed(Connection conn) throws SQLException { + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT 1"); + stmt.close(); + // :: error: (required.method.not.called) } + } From 235fc125271c77c85d0bbfae9a2daa08ce92a20b Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 23:03:13 +0530 Subject: [PATCH 6/9] Fix: comment formatting in RowSetResourceLeak test --- checker/tests/resourceleak/RowSetResourceLeak.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/tests/resourceleak/RowSetResourceLeak.java b/checker/tests/resourceleak/RowSetResourceLeak.java index 3ce9c692ab09..241abbde6546 100644 --- a/checker/tests/resourceleak/RowSetResourceLeak.java +++ b/checker/tests/resourceleak/RowSetResourceLeak.java @@ -36,7 +36,7 @@ void cachedRowSetToResultSetNotClosed() throws SQLException { CachedRowSet crs = new CachedRowSetImpl(); ResultSet rs = crs.toResultSet(); crs.close(); - // :: error: (required.method.not.called) + // :: error: (required.method.not.called) } void cachedRowSetToResultSetBothClosed() throws SQLException { From 87f4485f544972a89e8a9fe44b2abe6fde4bba7a Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 23:18:04 +0530 Subject: [PATCH 7/9] Test: cover scenario where both CachedRowSet and ResultSet are unclosed Added test for CachedRowSet to ResultSet without closing. --- checker/tests/resourceleak/RowSetResourceLeak.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/checker/tests/resourceleak/RowSetResourceLeak.java b/checker/tests/resourceleak/RowSetResourceLeak.java index 241abbde6546..efc11beb8b22 100644 --- a/checker/tests/resourceleak/RowSetResourceLeak.java +++ b/checker/tests/resourceleak/RowSetResourceLeak.java @@ -45,6 +45,13 @@ void cachedRowSetToResultSetBothClosed() throws SQLException { rs.close(); crs.close(); } + + void cachedRowSetToResultSetBothNotClosed() throws SQLException { + CachedRowSet crs = new CachedRowSetImpl(); + ResultSet rs = crs.toResultSet(); + // :: error: (required.method.not.called) + // :: error: (required.method.not.called) + } // ========== FilteredRowSet Tests ========== From c431545ea860899a935210a36a628a79c58cf5a4 Mon Sep 17 00:00:00 2001 From: "PARAMESH.N" Date: Fri, 6 Feb 2026 23:25:19 +0530 Subject: [PATCH 8/9] Update RowSetResourceLeak.java From 2759b85909367f666c95ec204b2d28ea53559927 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Wed, 4 Mar 2026 07:49:18 -0800 Subject: [PATCH 9/9] Put error message key in brackets --- checker/tests/resourceleak/JdbcResourceLeak.java | 10 +++++----- .../tests/resourceleak/RowSetResourceLeak.java | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/checker/tests/resourceleak/JdbcResourceLeak.java b/checker/tests/resourceleak/JdbcResourceLeak.java index 5327f4df35ab..2d9511605c6f 100644 --- a/checker/tests/resourceleak/JdbcResourceLeak.java +++ b/checker/tests/resourceleak/JdbcResourceLeak.java @@ -10,7 +10,7 @@ class JdbcResourceLeak { void resultSetNotClosed(Statement stmt) throws SQLException { ResultSet rs = stmt.executeQuery("SELECT 1"); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void resultSetClosed(Statement stmt) throws SQLException { @@ -22,7 +22,7 @@ void resultSetClosed(Statement stmt) throws SQLException { void statementNotClosed(Connection conn) throws SQLException { Statement stmt = conn.createStatement(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void statementClosed(Connection conn) throws SQLException { @@ -34,7 +34,7 @@ void statementClosed(Connection conn) throws SQLException { void preparedStatementNotClosed(Connection conn) throws SQLException { PreparedStatement ps = conn.prepareStatement("SELECT ?"); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void preparedStatementClosed(Connection conn) throws SQLException { @@ -55,14 +55,14 @@ void nestedStatementNotClosed(Connection conn) throws SQLException { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT 1"); rs.close(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void nestedResultSetNotClosed(Connection conn) throws SQLException { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT 1"); stmt.close(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } } diff --git a/checker/tests/resourceleak/RowSetResourceLeak.java b/checker/tests/resourceleak/RowSetResourceLeak.java index efc11beb8b22..4d583a2f809d 100644 --- a/checker/tests/resourceleak/RowSetResourceLeak.java +++ b/checker/tests/resourceleak/RowSetResourceLeak.java @@ -12,7 +12,7 @@ class RowSetResourceLeak { void jdbcRowSetNotClosed(ResultSet rs) throws SQLException { JdbcRowSet jrs = new JdbcRowSetImpl(rs); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void jdbcRowSetClosed(ResultSet rs) throws SQLException { @@ -24,7 +24,7 @@ void jdbcRowSetClosed(ResultSet rs) throws SQLException { void cachedRowSetNotClosed() throws SQLException { CachedRowSet crs = new CachedRowSetImpl(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void cachedRowSetClosed() throws SQLException { @@ -36,7 +36,7 @@ void cachedRowSetToResultSetNotClosed() throws SQLException { CachedRowSet crs = new CachedRowSetImpl(); ResultSet rs = crs.toResultSet(); crs.close(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void cachedRowSetToResultSetBothClosed() throws SQLException { @@ -49,15 +49,15 @@ void cachedRowSetToResultSetBothClosed() throws SQLException { void cachedRowSetToResultSetBothNotClosed() throws SQLException { CachedRowSet crs = new CachedRowSetImpl(); ResultSet rs = crs.toResultSet(); - // :: error: (required.method.not.called) - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] + // :: error: [required.method.not.called] } // ========== FilteredRowSet Tests ========== void filteredRowSetNotClosed() throws SQLException { FilteredRowSet frs = new FilteredRowSetImpl(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void filteredRowSetClosed() throws SQLException { @@ -69,7 +69,7 @@ void filteredRowSetClosed() throws SQLException { void webRowSetNotClosed() throws SQLException { WebRowSet wrs = new WebRowSetImpl(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void webRowSetClosed() throws SQLException { @@ -81,7 +81,7 @@ void webRowSetClosed() throws SQLException { void joinRowSetNotClosed() throws SQLException { JoinRowSet jrs = new JoinRowSetImpl(); - // :: error: (required.method.not.called) + // :: error: [required.method.not.called] } void joinRowSetClosed() throws SQLException {