gpt4 book ai didi

java - try-with-resources 和 HikariCP 的连接泄漏

转载 作者:搜寻专家 更新时间:2023-11-01 02:41:52 26 4
gpt4 key购买 nike

以下代码触发连接泄漏警告。我正在使用 OpenJDK 1.7.0_80 和 HikariCP 2.2.5(也可以使用最新的 HikariCP 2.3.9 重现)。我错过了什么吗?

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class HikaryAutoCloseTest {
private static HikariDataSource configureDataSource() {
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://127.0.0.1/DATABASE");
config.setUsername("USERNAME");
config.setPassword("PASSWORD");

config.setLeakDetectionThreshold(10000);

config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("useServerPrepStmts", "true");

return new HikariDataSource(config);
}

@Test
public void testHikaryAutoClose() {
HikariDataSource dataSource = configureDataSource();

boolean ret = shouldNotLeakConnection(dataSource);
if (ret) {
System.out.println("UPDATE okey");
}

/* Wait for LeakTask to complain */
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("Exiting");
}

private boolean shouldNotLeakConnection(HikariDataSource dataSource) {
String sql = "INSERT INTO error_logs (description) values (?)";

try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql);) {
stmt.setString(1, "description");
return stmt.executeUpdate() != 0; // minor changes to this line remove the leak
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

更新:稍微更改返回语句可消除泄漏:

private boolean shouldNotLeakConnection(HikariDataSource dataSource) {
String sql = "INSERT INTO error_logs (description) values (?)";

try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement(sql);) {
stmt.setString(1, "description");
boolean ret = stmt.executeUpdate() != 0;
return ret;
} catch (SQLException e) {
throw new RuntimeException(e);
}
}

最佳答案

问题似乎是由 AspectJ 1.7.2 中的错误引起的。它正在生成以下字节码:

  private boolean shouldNotLeakConnection(com.zaxxer.hikari.HikariDataSource);
Code:
0: ldc #115 // String INSERT INTO error_logs (description) values (?)
2: astore_2
3: aconst_null
4: astore_3
5: aconst_null
6: astore 4
8: aload_1
9: invokevirtual #117 // Method com/zaxxer/hikari/HikariDataSource.getConnection:()Ljava/sql/Connection;
12: astore 5
14: aload 5
16: aload_2
17: invokeinterface #121, 2 // InterfaceMethod java/sql/Connection.prepareStatement:(Ljava/lang/String;)Ljava/sql/PreparedStatement;
22: astore 6
24: aload 6
26: iconst_1
27: ldc #127 // String description
29: invokeinterface #129, 3 // InterfaceMethod java/sql/PreparedStatement.setString:(ILjava/lang/String;)V
34: aload 6
36: invokeinterface #135, 1 // InterfaceMethod java/sql/PreparedStatement.executeUpdate:()I
41: ifeq 46
44: iconst_1
45: ireturn
46: iconst_0
47: aload 6
49: ifnull 59
52: aload 6
54: invokeinterface #139, 1 // InterfaceMethod java/sql/PreparedStatement.close:()V
59: aload 5
61: ifnull 71
64: aload 5
66: invokeinterface #142, 1 // InterfaceMethod java/sql/Connection.close:()V
71: ireturn
72: astore_3
73: aload 6
75: ifnull 85
78: aload 6
80: invokeinterface #139, 1 // InterfaceMethod java/sql/PreparedStatement.close:()V
85: aload_3
86: athrow
87: astore 4
89: aload_3
90: ifnonnull 99
93: aload 4
95: astore_3
96: goto 111
99: aload_3
100: aload 4
102: if_acmpeq 111
105: aload_3
106: aload 4
108: invokevirtual #143 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
111: aload 5
113: ifnull 123
116: aload 5
118: invokeinterface #142, 1 // InterfaceMethod java/sql/Connection.close:()V
123: aload_3
124: athrow
125: astore 4
127: aload_3
128: ifnonnull 137
131: aload 4
133: astore_3
134: goto 149
137: aload_3
138: aload 4
140: if_acmpeq 149
143: aload_3
144: aload 4
146: invokevirtual #143 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
149: aload_3
150: athrow
151: astore_3
152: new #25 // class java/lang/RuntimeException
155: dup
156: aload_3
157: invokespecial #27 // Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V
160: athrow
Exception table:
from to target type
24 47 72 any
71 72 72 any
14 59 87 any
71 87 87 any
8 125 125 any
3 71 151 Class java/sql/SQLException
72 151 151 Class java/sql/SQLException

注意第 45 行,ireturn 跳过了两个 close() 方法。

使用 AspectJ 1.8.6,生成了正确的字节码:

  private boolean shouldNotLeakConnection(com.zaxxer.hikari.HikariDataSource);
Code:
0: ldc #115 // String INSERT INTO error_logs (description) values (?)
2: astore_2
3: aconst_null
4: astore_3
5: aconst_null
6: astore 4
8: aload_1
9: invokevirtual #117 // Method com/zaxxer/hikari/HikariDataSource.getConnection:()Ljava/sql/Connection;
12: astore 5
14: aload 5
16: aload_2
17: invokeinterface #121, 2 // InterfaceMethod java/sql/Connection.prepareStatement:(Ljava/lang/String;)Ljava/sql/PreparedStatement;
22: astore 6
24: aload 6
26: iconst_1
27: ldc #127 // String description
29: invokeinterface #129, 3 // InterfaceMethod java/sql/PreparedStatement.setString:(ILjava/lang/String;)V
34: aload 6
36: invokeinterface #135, 1 // InterfaceMethod java/sql/PreparedStatement.executeUpdate:()I
41: ifeq 48
44: iconst_1
45: goto 49
48: iconst_0
49: aload 6
51: ifnull 61
54: aload 6
56: invokeinterface #139, 1 // InterfaceMethod java/sql/PreparedStatement.close:()V
61: aload 5
63: ifnull 73
66: aload 5
68: invokeinterface #142, 1 // InterfaceMethod java/sql/Connection.close:()V
73: ireturn
74: astore_3
75: aload 6
77: ifnull 87
80: aload 6
82: invokeinterface #139, 1 // InterfaceMethod java/sql/PreparedStatement.close:()V
87: aload_3
88: athrow
89: astore 4
91: aload_3
92: ifnonnull 101
95: aload 4
97: astore_3
98: goto 113
101: aload_3
102: aload 4
104: if_acmpeq 113
107: aload_3
108: aload 4
110: invokevirtual #143 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
113: aload 5
115: ifnull 125
118: aload 5
120: invokeinterface #142, 1 // InterfaceMethod java/sql/Connection.close:()V
125: aload_3
126: athrow
127: astore 4
129: aload_3
130: ifnonnull 139
133: aload 4
135: astore_3
136: goto 151
139: aload_3
140: aload 4
142: if_acmpeq 151
145: aload_3
146: aload 4
148: invokevirtual #143 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
151: aload_3
152: athrow
153: astore_3
154: new #25 // class java/lang/RuntimeException
157: dup
158: aload_3
159: invokespecial #27 // Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V
162: athrow
Exception table:
from to target type
24 49 74 any
73 74 74 any
14 61 89 any
73 89 89 any
8 127 127 any
3 73 153 Class java/sql/SQLException
74 153 153 Class java/sql/SQLException

请注意,在第 45 行,ireturn 被替换为 goto,它不会跳过两个 close() 方法。

感谢@brettw 帮助我缩小问题范围。

关于java - try-with-resources 和 HikariCP 的连接泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31562581/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com