0

私はしばらくの間、この問題について頭を悩ませてきました。27K でエンコードされた文字列 (URL エンコードと同様) を取得し、それを 9K の "ISO-8859-1" プレーンテキスト文字列に戻しています。

byte outarray[] = new byte[decoded_msg_length]; // 9K
byte inarray[];
try {
  inarray = instring.getBytes("ISO-8859-1"); // eg: "ÀÀÀÚßÐÀÀÃÐéÙÓåäàÈÂÁÙÈ...."
  inarray = null; // free up whatever memory possible.
  // ... for loop decodes chunks of 4 bytes...

  Runtime runtime = Runtime.getRuntime();
  System.out.println("freeMemory1="+runtime.freeMemory()); // freeMemory1=86441120
  // yes I've tried methods like new String( outarray, "ISO-8859-1" );, etc.
  ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
  byteStream.write(outarray);
  outarray=null;
  runtime.gc();

  System.out.println("freeMemory2="+runtime.freeMemory()); //freeMemory2=133761568
  // return new String(outarray,"ISO-8859-1"); // OutOfMemoryException thrown here
  // return new String(outarray); // OutOfMemoryException thrown here too
  return byteStream.toString("ISO-8859-1"); // OutOfMemoryException thrown here also
  // sample output: "JOHN H SMITH  123 OAK ST..."
} catch( IOException ioe ) {
  ...
}
// Thrown exception:
Exception in thread "main" java.lang.OutOfMemoryError
    at java.lang.StringCoding.decode(StringCoding.java:510)
    at java.lang.String.<init>(String.java:232)
    at java.io.ByteArrayOutputStream.toString(ByteArrayOutputStream.java:195)
    ...

記憶力は結構あるみたいです。この同じコードは、Windows の半分以下の空きメモリで問題なく動作します。これを単一のスタンドアロン クラスとして実行しています。JREメモリリークに関するLinuxエンコーディングの問題を知っている人はいますか?

$ java -version
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build pxi32dev-20080315 (SR7))
IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20080315 (JIT enabled)
J9VM - 20080314_17962_lHdSMr
JIT  - 20080130_0718ifx2_r8
GC   - 200802_08)
JCL  - 20080314
4

2 に答える 2

1

Linux 環境と Windows では、Java ヒープ サイズのデフォルト制限が異なる場合があります。これは、Runtime.maxMemory() メソッドで確認できます。 http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Runtime.html#maxMemory ()

Linux で制限が小さい場合は、java への -Jmx コマンドライン引数を使用して制限を増やすことができます。

java -Xmx1024m YourClassNameHere

1024m はヒープのサイズを 1GB に増やします。必要に応じて量を調整できます。これは最大量であり、プログラムで使用する量はこれよりはるかに少ない場合があります。

于 2011-06-10T15:42:35.203 に答える
1

解決策を見つけましたが、それが発生する正確な理由はわかりません-おそらく内部静的バッファ変数です。エラーは toString でスローされますが、decoded_msg_length を instring と同じサイズに変更することで修正されました。

何らかの理由で、instring.getBytes("ISO-8859-1") は、byteStream.toString("ISO-8859-1") によって満たされた内部バッファーのサイズを設定します。decoded_msg_length のサイズをその長さより 1 バイト短く設定すると、Java がエラーをスローします。スレッドセーフでないものは何もなく、2 つの異なる変数を使用しています。

さらに、CharsetDecoder を使用できますが、それでも失敗します。OS JVM のバグのせいだと思います。その異常な修正がなければ、コードは他の OS や JVM で正常に動作します。

于 2011-06-12T05:43:20.520 に答える