Java内存溢出奇怪错误

3

我已经通过以下命令从命令行启动了我的jar文件:

java -Xms1200m -Xmx1500m -jar xxx.jar

我正在创建尺寸为12600 * 12600的BufferedImage,这意味着以下代码需要使用606 MB内存。
TranscoderInput input = new TranscoderInput(sr);

            String pngFile = "Style-" + shoeViewer.getCurrentStyle() + "_"
                    + shoeViewer.getSelectedMetadata().getSizeLabel()
                    + "_400DPI" + ".png";

            File outputFile = new File(pngFile);

            FileOutputStream fo = new FileOutputStream(outputFile);

            TranscoderOutput output = new TranscoderOutput(fo);

            long now = System.currentTimeMillis();

            t.transcode(input, null);

在执行以上代码之前,当我调试内存使用情况时,我的运行时显示:

我需要 606 MB 的内存,而 1100 MB 仍然可用。

所以当我在 34 分钟后运行以上代码时,它会抛出 OutOfMemory 异常。

问题是什么?是进程问题还是堆问题?为什么要花费 34 分钟?

我的 PC 配置如下:

Windows 32bit XP Service Pack2 Home Edition
Amd Athlon (tm) 7750 Dual Core 2.71 GHz
2GB of DDR2 RAM
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) Client VM (build 23.7-b01, mixed mode, sharing)

请帮我解决这个问题。

以下是具有调试消息的异常堆栈跟踪。

在运行上述代码之前,我更改了VM参数如下:

java -Xms900m -Xmx1024m -XX:MinHeapFreeRatio=40 -XX:MaxHeapFreeRatio=70 -jar myjar.jar

从SVG Reader构建XML文档......

XML文档从SVG Reader构建完成......

将修改后的XML文档转换为字符串编写器......

修改后的XML文档成功转换为字符串编写器......

已声明字节数766,可用字节数900189232

内存统计------------------------

总内存大小为字节:912326656 总内存大小为兆字节:870

已使用的内存大小为字节:9308384 已使用的内存大小为兆字节:8

可用的空闲内存大小为字节:900189096 可用的空闲内存大小为兆字节:858


转码开始时间:2013年3月24日星期日11:09:59 IST

Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap spa
ce
        at java.awt.image.DataBufferInt.<init>(Unknown Source)
        at java.awt.image.SinglePixelPackedSampleModel.createDataBuffer(Unknown
Source)
        at java.awt.image.Raster.createWritableRaster(Unknown Source)
        at org.apache.batik.gvt.renderer.StaticRenderer.updateWorkingBuffers(Sta
ticRenderer.java:536)
        at org.apache.batik.gvt.renderer.StaticRenderer.repaint(StaticRenderer.j
ava:375)
        at org.apache.batik.gvt.renderer.StaticRenderer.repaint(StaticRenderer.j
ava:344)
        at org.apache.batik.transcoder.image.ImageTranscoder.transcode(ImageTran
scoder.java:111)
        at org.apache.batik.transcoder.XMLAbstractTranscoder.transcode(XMLAbstra
ctTranscoder.java:142)
        at org.apache.batik.transcoder.SVGAbstractTranscoder.transcode(SVGAbstra
ctTranscoder.java:156)
        at com.mmg.app.eventlistener.PlaceOrderActionListener.save(PlaceOrderAct
ionListener.java:302)
        at com.mmg.app.eventlistener.PlaceOrderActionListener.saveCanvas(PlaceOr
derActionListener.java:270)
        at com.mmg.app.eventlistener.PlaceOrderActionListener.actionPerformed(Pl
aceOrderActionListener.java:143)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Sour
ce)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.awt.EventQueue.access$200(Unknown Source)

4
如果你知道答案,为什么不给出来呢? - Mihir
1
t是什么类型的对象? - ecbrodie
2
你应该使用-XX:+HeapDumpOnOutOfMemoryError标志,并分析堆转储。YourKit是一个非常好的工具,但JVisualVM也很容易使用,而且免费(你可以在JDK文件夹中找到它)。 - iGili
请提供OOM错误的堆栈跟踪信息。 - iGili
启用详细垃圾回收(-Xloggc:file)。这应该能够给出内存使用模式的想法。 - enigma
显示剩余6条评论
1个回答

2

即使未编码的原始图像只占用约600 MB的空间,但编码器内部表示可能需要更多的内存,具体取决于其实现方式。以下示例显示了将简单的SVG文件缩放到12600 x 12600(32位)时使用的内存量。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;

public class Test {
    public static void main(String[] args) throws Exception {
        PNGTranscoder t = new PNGTranscoder();
        t.addTranscodingHint(PNGTranscoder.KEY_WIDTH, new Float(12600));
        t.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, new Float(12600));
        FileInputStream fis = new FileInputStream("C:\\StackOverflow\\SVG-logo.svg");
        TranscoderInput input = new TranscoderInput(fis);
        OutputStream ostream = new FileOutputStream("C:\\StackOverflow\\res.png");
        TranscoderOutput output = new TranscoderOutput(ostream);

        System.out.println("AllocatedMemory: \t" + (Runtime.getRuntime().totalMemory() / 1024) + " Kb");
        t.transcode(input, output);
        System.out.println("AllocatedMemory: \t" + (Runtime.getRuntime().totalMemory() / 1024) + " Kb");

        ostream.flush();
        ostream.close();

    }
}

在我的电脑上输出结果为:

AllocatedMemory:    4096 Kb 
AllocatedMemory:    1677721 Kb

因此,该程序使用1677 MB将简单的SVG文件转码为12600 * 12600的PNG文件。


你的电脑有多少GB的RAM?在你的电脑上运行以上代码需要多长时间? - Mihir
好的,我在另一台内存更高的电脑上尝试了一下,它可以运行。现在,你能告诉我在哪种电脑配置下这段代码可以无问题地运行吗?你的JDK配置以及生成(转码)PNG文件在磁盘上的大小是多少MB? - Mihir
我电脑有8GB内存。我在程序中编码的文件来自维基百科:[链接]http://en.wikipedia.org/wiki/File:SVG-logo.svg,处理这个文件大约需要20秒钟,在我的电脑上生成一个大小为1.1MB的输出文件。我是在Eclipse中运行程序,没有使用任何特殊选项。 - Ebbe M. Pedersen
另外一件事是,使用多彩图像测试您的程序,并请告诉我生成的PNG文件的大小和生成文件所需的时间。您可以在此处找到大量多彩的SVG:http://raphaeljs.com/ - Mihir
为什么不自己做呢? - Ebbe M. Pedersen
目前我的电脑只有2GB的内存,所以我正遇到内存不足的错误。 - Mihir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接