3

次のようなシンプルでシンプルなコードを使用すると、メモリ リークが発生します。このコードは、ソースからファイルを取得し、各ファイルを使用して何かを実行し、続行することを目的としています。この単純なコードは常に同じファイルを使用しますが、動作は変わりません。

package it.datapump.main;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;


public class TifReader {

public static void main (final String[] a){

    for (int i = 0; i < 100000; i++) {
        try {
            getBytesFromFile(new File("test.tif"));
            Thread.sleep(1000);
            System.gc() ;
        } catch (Exception ex) {
        }
    }
}

public static byte[] getBytesFromFile(File file) throws IOException {
    InputStream is = new FileInputStream(file);
    long length = file.length();

    byte[] bytes = new byte[(int)length];
    int offset = 0;
    int numRead = 0;
    while (offset < bytes.length
           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
        offset += numRead;
    }
    is.close();

    // Do something with the read bytes
    //

    if (offset < bytes.length) {
        throw new IOException("Could not completely read file "+file.getName());
    }
    return bytes;
}
}

さて... このコードがメモリを消費し、最後に OutOfMemoryError 例外をスローする正当な理由がわかりません。
何か案が?

Java Development Kit Version 6 Update 23 を使用すると問題が発生します
が、JRE 1.7 では発生しません。

4

4 に答える 4

2

このコードは正常に実行されるはずです (新しいファイルを何度も作成しても意味がないという事実を除いて)。

コードを 1,000 万回ループで実行しましたが、OOME は生成されませんでした。実際、メモリ使用量は約 50Mb で一定でした。

ですから、問題は別のものであるべきだと思います。

于 2011-02-02T09:31:36.950 に答える
1

コードをVisual VMなどのプロファイラーに対して実行し、メモリが使い果たされている場所を確認します。

「バイトコードで何か」を行うと問題が発生する可能性があると推測しています。また、System.gc() の呼び出しは、ガラブジ コレクターがいつ呼び出されるべきかを認識している必要があるため、通常はお勧めしません。

于 2011-02-02T09:39:10.727 に答える
0


これで時間とヘルスを失った後、問題はパッケージがターゲットマシンにどのようにインストールされたかに起因することがわかりました.
私たちのプログラマーは、ターゲット マシンに既にインストールされているものを使用する代わりに、必要なすべての jar を含む実行可能な jar を作成しました。だから...「何か」は違いましたが、実際には何がわからなくても、手順はもうメモリを失いません。

誰かが私にこれを説明できますか? (私は Java 開発者ではなく C/C++ 開発者であり、私の同僚の仕事について書いていると言わざるを得ません)。

于 2011-02-03T09:53:48.147 に答える
0

Xmx各反復でファイルから読み取ったバイトを効果的に破棄しているため、ファイルのサイズがJVM プロセスのデフォルトを超えない限り、OOME を取得する理由はわかりません(TIF ファイルが他の画像形式と比べてサイズが大きいことで有名です)。

また、反復番号を出力します。常に同じ反復回数で OOME を取得しますか? それとも、ファイルストリームから読み取ったバイトを「使用」しているのですか?

于 2011-02-02T09:40:55.077 に答える