[英]Why doesn't this code close JDBC connections? (Java 7 Autocloseable unexpected behavior)
使用Java 7u5和try-with-resources构造,以下代码似乎泄漏了jdbc连接 :
try (Connection connection = ..; PreparedStatement stmt = ..) {
stmt.setString(..);
return stmt.executeUpdate() > 0;
}
下一段代码按预期和预期工作:
int ret = 0;
try (Connection connection = ..; PreparedStatement stmt = ..) {
stmt.setString(..);
ret = stmt.executeUpdate();
}
return ret > 0;
似乎在第一种情况下,没有调用Connection.close()
方法。
我正在使用最新的mysql连接器。 这是出乎意料的行为,对吗?
以下测试不会打印CLOSED
:
public class Test implements AutoCloseable {
public static void main(String[] args) throws Exception {
System.out.println(doTest());
}
private static boolean doTest() throws Exception {
try (Test test = new Test()) {
return test.execute() > 0;
}
}
private int execute() {
return 1;
}
@Override
public void close() throws Exception {
System.out.println("CLOSED");
}
}
奇怪的是,如果execute()
被修改为return 0;
然后将打印已CLOSED
。
Compiled from "Test.java"
public class Test implements java.lang.AutoCloseable {
public Test();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #27 // Method doTest:()Z
6: invokevirtual #31 // Method java/io/PrintStream.println:(Z)V
9: return
private static boolean doTest() throws java.lang.Exception;
Code:
0: aconst_null
1: astore_0
2: aconst_null
3: astore_1
4: new #1 // class Test
7: dup
8: invokespecial #39 // Method "<init>":()V
11: astore_2
12: aload_2
13: invokespecial #40 // Method execute:()I
16: ifle 21
19: iconst_1
20: ireturn
21: iconst_0
22: aload_2
23: ifnull 30
26: aload_2
27: invokevirtual #44 // Method close:()V
30: ireturn
31: astore_0
32: aload_2
33: ifnull 40
36: aload_2
37: invokevirtual #44 // Method close:()V
40: aload_0
41: athrow
42: astore_1
43: aload_0
44: ifnonnull 52
47: aload_1
48: astore_0
49: goto 62
52: aload_0
53: aload_1
54: if_acmpeq 62
57: aload_0
58: aload_1
59: invokevirtual #47 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
62: aload_0
63: athrow
Exception table:
from to target type
12 22 31 any
30 31 31 any
4 42 42 any
private int execute();
Code:
0: iconst_1
1: ireturn
public void close() throws java.lang.Exception;
Code:
0: getstatic #21 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #55 // String CLOSED
5: invokevirtual #57 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
升级到最新版本的eclipse(Juno)后,这种奇怪的行为不再发生。
它也可以使用命令行进行编译和运行。
我怀疑Eclipse Indigo使用旧的javac
进行编译,而不是抱怨任何违规行为。
我使用JDK 1.7.0_17遇到了同样的问题。 仔细消除之后,事实证明我的IntelliJ正在使用AspectJ编译器。 一旦我用JDK的javac显式编译了它,它就按预期工作了。
我的同事已向AspectJ人员提交了一份错误报告 。 他们已经安排了1.7.3版本的修复程序
这是一个java 7u5的bug; 去注册一个bug。 Java 7u4工作。
return test.execute() > 0;
为0提供错误的代码:
13: invokespecial #40 // Method execute:()I
16: ifle 21
19: iconst_1
20: ireturn
在Eclipse Juno
它运行良好。 我不认为这是一个java 7的bug。 从Eclipse Indigo
运行时它无法正常工作。
它也适用于Command Line
。
在下面的情况下,我运行你的程序,它工作,我正在检查你的情况
情况1 :
public class Test implements AutoCloseable {
public int execute() {
return 1;
}
@Override
public void close() throws Exception {
System.out.println("CLOSED");
}
}
public class Test1 {
public static void main(String[] args) throws Exception {
try (Test test = new Test()) {
System.out.println(test.execute() > 0);
}
}
}
输出:
true
CLOSED
案例2:
public class Test implements AutoCloseable {
public static void main(String[] args) throws Exception {
System.out.println(doTest());
}
private static boolean doTest() throws Exception {
try (Test test = new Test()) {
throw new ArrayIndexOutOfBoundsException("exc"); // just for testing
//return test.execute() > 0;
}
}
private int execute() {
return 1;
}
@Override
public void close() throws Exception {
System.out.println("CLOSED");
}
}
输出:
CLOSED
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: exc
at com.aquent.rambo.auth.Test.doTest(Test.java:11)
at com.aquent.rambo.auth.Test.main(Test.java:6)
案例3: Here this is wierd, and it works
public class Test implements AutoCloseable {
public static void main(String[] args) throws Exception {
System.out.println(doTest());
}
private static boolean doTest() throws Exception {
try (Test test = new Test()) {
boolean result = test.execute() > 0; // Change : result variable declared
return result;
}
}
private int execute() {
return 1;
}
@Override
public void close() throws Exception {
System.out.println("CLOSED");
}
}
输出:
CLOSED
true
您是否尝试在完成后关闭语句和/或连接。
还要确保在finally块中执行此操作:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.