13

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 れます。

javap -p-cTest.class出力

    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
}
4

5 に答える 5

3

最新バージョンのEclipse(Juno)にアップグレードした後、この奇妙な動作は発生しなくなりました。

また、コマンドラインを使用してコンパイルおよび実行しても正常に機能します。

Eclipse Indigoがjavacコンパイルに古いものを使用していて、コンプライアンス違反について不平を言っていなかったのではないかと思います。

于 2012-07-16T15:36:05.443 に答える
2

JDK1.7.0_17を使用してまったく同じ問題が発生しました。注意深く排除した後、私のIntelliJがAspectJコンパイラを使用していたことが判明しました。JDKのjavacを使用してクラスを明示的にコンパイルすると、期待どおりに機能しました。

私の同僚はAspectJの人々にバグレポートを提出しました。彼らはバージョン1.7.3の修正を予定しています

于 2013-03-22T08:05:39.723 に答える
1

これはJava7u5のバグです。バグを登録してください。 Java7u4は機能しました。

return test.execute() > 0;

> 0に対して間違ったコードを与える:

  13: invokespecial #40                 // Method execute:()I
  16: ifle          21
  19: iconst_1
  20: ireturn
于 2012-07-16T15:16:42.880 に答える
0

編集

  1. そのEclipse Juno中で非常にうまく機能します。Java7のバグではないと思います。から実行すると機能しませんEclipse Indigo

  2. からも動作し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
于 2012-07-16T15:06:18.650 に答える
-3

完了した後、ステートメントや接続を閉じようとしましたか。

また、finallyブロックでこれを行うようにしてください。

于 2012-07-16T01:53:55.283 に答える