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

Java 堆大小在您的 Linux 环境与 Windows 中可能具有不同的默认限制。您可以通过 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 的大小设置为比该长度短一个字节会导致 Java 抛出错误,即使没有任何线程不安全,并且我正在使用两个不同的变量。

最重要的是,我可以使用 CharsetDecoder ,但它仍然会失败。我将其归结为 OS JVM 错误。如果没有那个怪异的修复,代码在其他操作系统和 JVM 中运行良好。

于 2011-06-12T05:43:20.520 回答