次のコードで、Eclipseが「リソースリーク: 'in'が閉じられない」という警告を出すのはなぜですか?
public void readShapeData() {
Scanner in = new Scanner(System.in);
System.out.println("Enter the width of the Rectangle: ");
width = in.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = in.nextDouble();
スキャナーを閉じないため
in.close();
他の人が言ったように、IOクラスで 'close'を呼び出す必要があります。私はこれがtryを使用するのに最適な場所であることを追加します-最後にキャッチなしでブロックします:
public void readShapeData() throws IOException {
Scanner in = new Scanner(System.in);
try {
System.out.println("Enter the width of the Rectangle: ");
width = in.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = in.nextDouble();
} finally {
in.close();
}
}
これにより、スキャナーが常に閉じられ、適切なリソースのクリーンアップが保証されます。
同様に、Java 7以降では、「try-with-resources」構文を使用できます。
try (Scanner in = new Scanner(System.in)) {
...
}
確実に発生させるには、finally
ブロックでin.close()
を呼び出す必要があります。
Eclipseのドキュメントから、whyこの特定の問題にフラグを立てる(emphasis鉱山):
インターフェイスを実装するクラスJava.io.Closeable(JDK 1.5以降)およびJava.lang.AutoCloseable(JDK 1.7以降)は外部リソースを表すと見なされます。外部リソースは、不要になったらclose()メソッドを使用して閉じる必要があります。
Eclipse Javaコンパイラーは、そのようなタイプを使用するコードがこのポリシーに準拠しているかどうかを分析できます。
...
コンパイラは、[リソースリーク: 'ストリーム'が閉じられない]というフラグを[違反]に付けます。
完全な説明 こちら 。
Scanner.close()
を使用して、System.in
でインスタンス化したスキャナーを閉じる必要があることを伝えています。通常、すべてのリーダーを閉じる必要があります。
System.in
を閉じると、再度読み取ることができないことに注意してください。 Console
クラスもご覧ください。
public void readShapeData() {
Console console = System.console();
double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
...
}
JDK7または8を使用している場合、リソースでtry-catchを使用できます。これにより、スキャナーが自動的に閉じられます。
try ( Scanner scanner = new Scanner(System.in); )
{
System.out.println("Enter the width of the Rectangle: ");
width = scanner.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = scanner.nextDouble();
}
catch(Exception ex)
{
//exception handling...do something (e.g., print the error message)
ex.printStackTrace();
}
close 完了したらスキャナーを使用する必要があります。
in.close();
private static Scanner in;
を追加しても問題は実際には修正されず、警告がクリアされるだけです。スキャナーを静的にすることは、永久に(またはクラスがアンロードされるまで(ほぼ「永久に」)オープンのままになることを意味します。あなたは彼に「それを永遠に開いておく」と言ったので、コンパイラはもう警告を与えません。ただし、リソースが不要になったらすぐにリソースを閉じる必要があるため、これは本当に望んでいたことではありません。
HTH、マンフレッド。
一般に、I/Oを処理するクラスのインスタンスは、それらの処理が終了した後に閉じる必要があります。したがって、コードの最後にin.close()
を追加できます。
// An InputStream which is typically connected to keyboard input of console programs
Scanner in= new Scanner(System.in);
上記の行は、System.in引数を使用してScannerクラスのコンストラクタを呼び出し、新しく構築されたオブジェクトへの参照を返します。
これはキーボードに接続されている入力ストリームに接続されているため、実行時にユーザー入力を使用して必要な操作を実行できます。
//Write piece of code
メモリリークを削除するには-
in.close();//write at end of code.
private static Scanner in;
プライベートの静的Scannerクラス変数として宣言することで修正しました。なぜそれが修正されたのかはわかりませんが、それがEclipseが私が推奨したことです。
スキャナーを閉じてください。 Readers、Streams ...、およびこの種のオブジェクトを閉じて、リソースとaovidメモリリークを解放することをお勧めします。そして、これらのオブジェクトの処理中に例外が発生した場合でも、それらが閉じられるように、finallyブロックでそうします。
Scanner sc = new Scanner(System.in);
//do stuff with sc
sc.close();//write at end of code.