1

整数を含む大きなtxtファイルがあります。ファイルの各行には、空白で区切られた 2 つの整数があります。ファイルのサイズは 63 Mb です。

Pattern p = Pattern.compile("\\s");
    try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
        String line;
        while ((line = reader.readLine()) != null) {
            String[] tokens = p.split(line);
            String s1 = new String(tokens[0]);
            String s2 = new String(tokens[1]);
            int startLabel = Integer.valueOf(s1) - 1;
            int endLabel = Integer.valueOf(s2) - 1;
            Vertex fromV = vertices.get(startLabel);
            Vertex toV = vertices.get(endLabel);
            Edge edge = new Edge(fromV, toV);
            fromV.addEdge(edge);
            toV.addEdge(edge);
            edges.add(edge);
            System.out.println("Edge from " + fromV.getLabel() + " to " + toV.getLabel());
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Arrays.java:2694)
at java.lang.String.<init>(String.java:203)
at java.lang.String.substring(String.java:1913)
at java.lang.String.subSequence(String.java:1946)
at java.util.regex.Pattern.split(Pattern.java:1202)
at java.util.regex.Pattern.split(Pattern.java:1259)
at SCC.main(SCC.java:25)

なぜこの例外が発生するのですか? コードを変更して回避するにはどうすればよいですか?

編集: 私はすでにヒープ サイズを 2048m に増やしています。それを消費しているのは何ですか?それは私も知りたいです。

私が知っている限り、jvmは頂点のリスト、エッジのセット、バッファリングされたリーダーのバッファ、および1つの小さな文字列「行」にメモリを割り当てる必要があります。この outOfMemory がどこから来ているのかわかりません。

string.split() メソッドについて読みました。メモリリークが発生していると思いますが、どうすればよいかわかりません。

4

7 に答える 7

2

プログラムが Java ヒープに保存しているデータが多すぎるため、この例外が発生しています。

例外は Pattern.split() メソッドに表示されていますが、実際の原因は、作成中のグラフなど、コード内の大容量メモリ ユーザーである可能性があります。あなたが提供したものを見ると、グラフのデータ構造に多くの冗長データが格納されていると思われます。よりスペース効率の良いグラフ構造を調査することをお勧めします。

Sun JVM を使用している場合は、JVM オプション -XX:+HeapDumpOnOutOfMemoryError を試してヒープ ダンプを作成し、それを分析してメモリを大量に使用しているユーザーを見つけ、その分析を使用してコードを最適化します。詳細については、JBoss のヒープ ダンプに HeapDumpOnOutOfMemoryError パラメータを使用するを参照してください。

他の人が指摘しているように、それが面倒な場合は、プログラムがクラッシュしなくなるまで JVM ヒープ領域を増やしてみてください。

于 2013-07-30T16:02:30.810 に答える
0

何かを解析しようとしているときに OOM が発生した場合は、使用しているメソッドがスケーラブルでないというだけです。ヒープを増やすと一時的に問題が解決する可能性がありますが、スケーラブルではありません。たとえば、明日、ファイル サイズが 1 桁または 1 桁増加した場合、振り出しに戻ることになります。ファイルを分割して読み取り、ファイルの x 行をキャッシュし、読み取り、キャッシュをクリアして、プロセスをやり直すことをお勧めします。ehcache または guava キャッシュのいずれかを使用できます。

于 2013-07-30T16:01:37.127 に答える
0

文字列を解析する方法は変更される可能性があります。

try (Scanner scanner = new Scanner(new FileReader(filePath))) {
    while (scanner.hasNextInt()) {
        int startLabel = scanner.nextInt();
        int endLabel = scanner.nextInt();
        scanner.nextLine(); // discard the rest of the line.
        // use start and end.

    }

メモリ消費は、実際にはデータの読み取り方法ではなく、構築したデータ構造にあると思われますが、これにより、より明確になるはずです。

于 2013-07-30T16:02:55.583 に答える
-1

ヒープスペースが終了したため、例外があります。でヒープを増やしてみてください

 java -Xms512 -Xmx2048 (for example)
于 2013-07-30T15:53:30.677 に答える