リソースリーク:「in」が閉じられることはありません


84

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();

回答:


69

スキャナーを閉じないので

in.close();

39
これによりScanner、警告が閉じて無音になりますが、System.in通常は望ましくないことも閉じます。
スチュアートクック

@ StuartCook + 1。目を離さない何か。
informatik01

7
なぜスキャナーを閉じる必要があるのですか?「リソースリーク」とはどういう意味ですか?
Erran Morad 2014

1
@nogard:これは本当に役に立ちます..しかし、in.close(); ..を使用すると、解決できないことが示されます..例外処理なしのコードがあります..ありがとう
pcs

3
@StuartCook、あなたはなぜ閉鎖System.inが一般的に望ましくないのについて言及するのを忘れました。二度と読めなくなるからです。I.e。あなたが例えばjava.util.NoSuchElementException: No line found電話(new Scanner(System.in)).nextLine()をかけようとするとあなたは得るでしょう。
ペトルBodnarさん

55

他の人が言っているように、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)) {
    ... 
}

2
リソースリークとはどういう意味ですか?それは私にどのように影響しますか?
Erran Morad 2014

7
@ Borat-「リソースリーク」は、一部のシステムリソース(通常はメモリ)が失われているか、不必要に浪費されていることを意味します。通常、これは、プログラムの通常の操作中にOutOfMemoryErrorsがスローされ始めたときに影響します。
エリックリンダウアー2014年

エリックありがとう。無限ループで文字列をそれ自体に追加すると、エラーが発生する可能性があることを私は知っています。スキャナーがどのようにそのエラーを引き起こす可能性があるのか​​わかりません。
Erran Morad 2014

4
リソースを試すのはどうですか?
Dennis Meng

デニスに感謝します、と付け加えました。
エリックリンダウアー2016

12

それが確実に発生するようin.close()に、finallyブロック内でを呼び出す必要があります。

Eclipseのドキュメントから、この特定の問題にフラグを立てる理由は次のとおりです(私の強調)。

インターフェイスjava.io.Closeable(JDK 1.5以降)およびjava.lang.AutoCloseable(JDK 1.7以降)を実装するクラスは、外部リソースを表すと見なされます。これらは、不要になったときにメソッドclose()を使用して閉じる必要があります。

Eclipse Javaコンパイラーは、そのようなタイプを使用するコードがこのポリシーに準拠しているかどうかを分析できます。

..。

コンパイラは[違反]に「リソースリーク:「ストリーム」は決して閉じられません」というフラグを立てます。

ここで完全な説明。


7

あなたが上でインスタンス化スキャナクローズする必要があることを語っているSystem.inとしますScanner.close()。通常、すべてのリーダーを閉じる必要があります。

を閉じると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: "));
    ...
}

3
System.console()Eclipseを介してアプリケーションを実行する場合は使用できないことに注意してください。これは、開発中に面倒になる可能性があります。
スチュアートクック

6

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();
}

catch句は必須ではないことに注意してください。例外が発生した場合でもリソースが確実に閉じられるようにしたいが、例外の処理はOPの元のコードと同じままにする(つまり、まったくキャッチされない)場合はtry、示されているcatchとおりに使用でき、句は使用できません。
user118967

5
// 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.


3

追加private static Scanner in;しても実際には問題は解決せず、警告がクリアされるだけです。スキャナーを静的にするということは、スキャナーが永久に開いたままになることを意味します(または、クラスがアンロードされるまで、ほぼ「永久」です)。コンパイラは、「永久に開いたままにしておく」と言ったので、警告はもう表示されません。しかし、それはあなたが本当に望んでいたことではありません。なぜなら、リソースが不要になったらすぐに閉じる必要があるからです。

HTH、マンフレッド。


2

通常、I / Oを処理するクラスのインスタンスは、終了後に閉じる必要があります。したがって、コードの最後にを追加できin.close()ます。


2
private static Scanner in;

プライベート静的Scannerクラス変数として宣言することで修正しました。なぜそれが修正されたのかはわかりませんが、それが日食が私に勧めたものです。


5
警告をミュートしましたが、リソースリークが発生しました
zacheusz 2014

1

スキャナーを閉じる必要があります。リーダー、ストリーム、およびこの種のオブジェクトを閉じて、リソースを解放し、メモリリークを回避することをお勧めします。そしてfinallyブロックでこれを行い、それらのオブジェクトの処理中に例外が発生した場合でも、それらが閉じられるようにします。


この答えは、実際にOPが物事を閉じる必要がある理由を知るのに役立ちます。確かに、彼はドキュメントを読んで「scanner.close()」を見ることができますが、この答えは彼/彼女が何が起こっているのかを理解するのに本当に役立ちます。+ 1
HyperNeutrino 2015

1

さて、真剣に、少なくとも多くの場合、これは実際にはバグです。これはVSCodeにも表示され、スキャナーオブジェクトを閉じずに囲んでいるスコープの終わりに到達したことに気づきますが、開いているすべてのファイル記述子を閉じることがプロセス終了の一部であることを認識していません。終了時にリソースがすべてクリーンアップされ、プロセスが終了し、リソースを保持する場所がなくなるため、リソースリークは発生しません。


0
Scanner sc = new Scanner(System.in);

//do stuff with sc

sc.close();//write at end of code.

-1
in.close();
scannerObject.close(); 

Scanner警告を閉じて閉じます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.