gpt4 book ai didi

java - 在循环中实例化对象而不会出现 OutOfMemoryError : Java heap space

转载 作者:行者123 更新时间:2023-12-04 04:54:26 28 4
gpt4 key购买 nike

我必须创建一个函数,它接收一个条目 List<PDXObjectImage> list并为每个元素创建一个小图标并将它们存储在 JTable 中。

现在我找到了一种从 PDXObjectImage 创建图标的方法不加载整个图像,这样我的程序就不会抛出 OutOfMemoryError: Java heap space :

for(int k=0;k<list.size();k++)
{
ByteArrayOutputStream output = new ByteArrayOutputStream();
list.get(k).write2OutputStream(output);
ByteArrayInputStream bais = new ByteArrayInputStream(output.toByteArray());
ImageInputStream iis = ImageIO.createImageInputStream(bais);
Iterator iter = ImageIO.getImageReaders(iis);
if (iter.hasNext()) {
ImageReader reader = (ImageReader) iter.next();
reader.setInput(iis, true, true);
ImageReadParam params = reader.getDefaultReadParam();
params.setSourceSubsampling(2.0, 2.0, 0, 0);
BufferedImage img = reader.read(0, params);
ImageIcon imageIcon = new ImageIcon(img);
model.addRow(new Object[]{imageIcon});
}
}

我设法避免了 OutOfMemoryError: Java heap space对于列表中的少量图片,使用阅读器而不是将图片加载为 BufferedImage每次。
不幸的是,当列表中存储的元素超过 84 个时,我仍然收到此错误。

我使用 jvisualvm 查看哪些对象占用了所有堆空间,我发现它是 byte[]对象(约 85%)。

问题显然位于我创建所有流以获取 iconImage 的位置。 .
问题是我不知道如何获得 ImageInputStream无需每次都创建新的流。

我试图通过在单个函数中生成所有流来避免这个问题:
private ImageInputStream fct(PDXObjectImage img) throws IOException{
ByteArrayOutputStream output = new ByteArrayOutputStream();
img.write2OutputStream(output);
ByteArrayInputStream bais = new ByteArrayInputStream(output.toByteArray());
return ImageIO.createImageInputStream(bais);
}

认为java会在到达范围末尾时自动删除对象。

我尝试在每个循环结束时以任何可能的顺序添加以下内容:
output.reset();
output.flush();
bais.reset();
bais.close();
iis.flush();
output=null;
bais=null;
iis=null;
System.gc();

我还尝试在函数范围之外实例化流,但无法设置 ByteArrayInputStream来自 byte[]不使用 new关键字,从而创建一个新对象。

我仍然遇到同样的错误,没有任何效果。

我在 Statements 上阅读了一些帖子和 ResultSets但我没有发现它们相关。 (也许我错了)

如果有人对我如何避免此错误有任何想法,我将不胜感激。

谢谢

编辑:

我修改了我的代码,以便得到以下内容:
for(int k=0;k<list.size();k++)
{
list.get(k).write2OutputStream(cbb.getOutputStream());
ImageInputStream iis = ImageIO.createImageInputStream(cbb.getInputStream());
Iterator iter = ImageIO.getImageReaders(iis);
if (iter.hasNext()) {
ImageReader reader = (ImageReader) iter.next();
reader.setInput(iis, true, true);
BufferedImage img = reader.read(0, null);
ImageIcon imageIcon = new ImageIcon(img);
model.addRow(new Object[]{imageIcon});
}
}

我还为阅读器添加了一个监听器,以便它打印出阅读完成的百分比。它总是上升到 84.2% 并停止。

有谁知道这怎么可能?

最佳答案

使用 PipedInputStream/PipedOutputStreamCircularByteBuffer将字节直接写入输入流。这样您就不必创建中间流和浪费内存。

看看这个帖子:

http://ostermiller.org/convert_java_outputstream_inputstream.html

重写 fct使用方法 CircularByteBuffer :

private ImageInputStream fct(PDXObjectImage img) throws IOException{
CircularByteBuffer cbb = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
img.write2OutputStream(cbb.getOutputStream());
return ImageIO.createImageInputStream(cbb.getInputStream());
}

您还可以使用多线程方法,在一个线程中写入字节并在另一个线程中读取。因此,写入/读取可以同时发生以优化 CPU 使用率和内存使用率。

注: com.Ostermiller.util.CircularByteBuffer不是标准的 Java API。但来源是 freely available

关于java - 在循环中实例化对象而不会出现 OutOfMemoryError : Java heap space,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16962012/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com