-1

有罪のコードは次のとおりです。

// Demo the java.lang.OutOfMemoryError: Java heap space error.

    import java.util.*;

    public class Bozo {

      void TstReadFile() {
        SubBozo sb = new SubBozo();
        sb.readFile();
      }

   public static void main(String[] args) {
      Bozo b = new Bozo();
      b.TstReadFile();
    }
  }


/** Read in the observing list file. */

import java.io.*;
import java.util.*;

public class SubBozo {

  public boolean readFile() {

    int lineCt = 0;          // Count the lines read in observingList.

    long heap,
         heapMaxSize,
         heapFreeSize;

    String s = "Unstarted";

    FileInputStream fis = null;
    DataInputStream in = null;
    BufferedReader br = null;

    try {
      fis = new FileInputStream("../data/observingList");
      in = new DataInputStream(fis);
      br = new BufferedReader(new InputStreamReader(in));
    } catch (Exception e) {
      System.out.println("Couldn't open ../data/observingList because " +
                         e.getMessage());
    }

    boolean go = true;
    while (go) {
      try {
        s = br.readLine();  // Lines should not be longer than say 256 characters.
      } catch (Exception e) {
        System.out.println("Couldn't read ../data/observingList because " +
                           e.getMessage());
        heap = Runtime.getRuntime().totalMemory();
        heapMaxSize = Runtime.getRuntime().maxMemory();
        heapFreeSize = Runtime.getRuntime().freeMemory();
        System.out.println("" + lineCt + ") " + "Total Memory (MB): " +
                           (heap / 1048576) + "\n  Heap Max Size (MB): " +
                           (heapMaxSize / 1048576) +
                           "\n  Heap Free Size (MB): " +
                           (heapFreeSize / 1048576));
        go = false;
      }

      if ((lineCt++ % 1000) == 0) {
        System.gc();
        heap = Runtime.getRuntime().totalMemory();
        heapMaxSize = Runtime.getRuntime().maxMemory();
        heapFreeSize = Runtime.getRuntime().freeMemory();
        System.out.println("" + lineCt + ") " + "Total Memory (MB): " +
                           (heap / 1048576) + "\n  Heap Max Size (MB): " +
                           (heapMaxSize / 1048576) +
                           "\n  Heap Free Size (MB): " +
                           (heapFreeSize / 1048576));
      }
    }

    try {
      br.close();
      in.close();
      fis.close();
    } catch (Exception e) {
      System.out.println("Couldn't close the input file stream because " +
                         e.getMessage());
    }
    return true;
  }
}

これを実行するときは、次のコマンドを使用します。

nebula:finderChart/src java ボゾ

メモリ不足エラーをスローします。印刷物は次のとおりです。

1) 合計メモリ (MB): 119 ヒープ最大サイズ (MB): 1776 ヒープ空きサイズ (MB): 118

1001) 合計メモリ (MB): 119 ヒープ最大サイズ (MB): 1776 ヒープ空きサイズ (MB): 119

2001) 合計メモリ (MB): 119 ヒープ最大サイズ (MB): 1776 ヒープ空きサイズ (MB): 119

3001) 合計メモリ (MB): 119 ヒープ最大サイズ (MB): 1776 ヒープ空きサイズ (MB): 119

スレッド「メイン」での例外 java.lang.OutOfMemoryError: java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100) の java.util.Arrays.copyOf(Arrays.java:2882) の Java ヒープ スペース。 AbstractStringBuilder.append(AbstractStringBuilder.java:515) で java.lang.StringBuffer.append(StringBuffer.java:306) で java.io.BufferedReader.readLine(BufferedReader.java:345) で java.io.BufferedReader.readLine(BufferedReader) .java:362) で SubBozo.readFile(SubBozo.java:34) で Bozo.TstReadFile(Bozo.java:10) で Bozo.main(Bozo.java:15) で

さて、奇妙な部分ですが、あなたはすでにそれを見たことがあると思います. JVM は 1000 行ごとにメモリ使用量を出力します。メモリ不足ではありません。

エラーがスローされると、キャッチが失われます。

試す {

 s = br.readLine();

キャッチ(例外e){

 System.out.println("Couldn't read ../data/observingList because " 
 ...

}

それでは、メモリを増やしてみましょう: java -Xmx1024m Bozo

同じ結果なので、繰り返しません。

読み取られているファイル、obasrvingList に非常に長い (> 2048 バイト) 行が含まれていました。これは Java を驚かせましたが、Vim でファイルを編集しようとして、vim で編集できないことが判明するまでは、非常に長い行が一般的なテキスト リーダーにとって問題であることが明らかになりました。

ティア

トム

4

2 に答える 2

3

あなたは何も質問していませんが、ここにいくつかの答えがあります:

エラーがスローされると、キャッチを見逃します。

あなたが捕まえているのでExceptionOutOfMemoryErrorそれを拡張していません。そして、例外をログに記録している間、スタックトレースを無視しているので、神に感謝します。

System.out.println("Couldn't read ../data/observingList because " +
                       e.getMessage());

代わりに、常に以下を使用してください。

e.printStackTrace();

以上-ロギングフレームワークを使用します

メモリが不足していません。

そうですね。大きすぎるアレイを割り当てようとします(たとえば、50 MiBが空いていて、60 MiBを割り当てようとします)。これがどのようにStringBuffer機能するかです。古い配列と新しい配列への参照を一時的に保持しながら、内部配列のサイズを2倍にします。

何が起こったのかというと、読み取られているファイルobasrvingListには、非常に長い(> 2048バイト)行が含まれていました。これはJavaを驚かせましたが、Vimでファイルを編集しようとするまではありませんでした

2048文字はJVMには何の意味もありません。問題のある行には少なくとも数百万の文字が含まれていると思います... でさえそのファイル(おそらくこれまでで最も最適化されたエディター)を開くことができなかったので、行はおそらくめちゃくちゃ長いです。

また、全体的なコード品質(例外を飲み込んでループを制御するブールフラグを返すなどfalse)についての提案はほとんどありませんが、これはhttp://codereview.stackexchange.comgoに適しています。

于 2012-04-14T19:45:12.850 に答える
1

BufferredReader.readLinenullデータがない場合は返され、例外はスローされません。コードを次のように変更します。

 while (go) {
     s = br.readLine();
     if (s = null) break;

例外を処理する代わりに。そのため、コードがサイクルを離れることはなく、おそらくメモリを無限に割り当てようとしています。

于 2012-04-14T19:39:54.007 に答える