我正在编写一个JavaSwing应用程序,它将从磁盘加载大约1500个png图像,每个图像的大小从50kb到75kb不等。我不需要一次加载所有的图像,但是我需要一次加载50个图像。我试着用典型的
new javax.swing.ImageIcon(getClass().getResource("myimage.jpeg")
但是我的应用程序冻结了,在大约前30个图像之后,我的内存就用完了。
加载这些映像的最佳方式是什么?这样我就不会使jvm过载,并且能够监视到目前为止哪些映像已成功加载?如果可能和必要的话,我不介意应用程序在加载图像时显示一个“加载…”屏幕,但我不知道怎么做。
缓存在这里有用吗?我不太明白,但我看到了关于使用mediatracker的问题,我不知道如何在这里实现。
5条答案
按热度按时间fnx2tebb1#
为什么不为每个图像创建一个 Package 器对象,按需加载它们,并使用weakreference或softreference呢。这样,垃圾收集器可以在需要时对图像数据进行装箱,并且可以在清除弱引用时重新加载。
好处是,当需要用于其他用途时,可以清除图像的内存。缺点是,您必须在显示之前重新加载图像(或对图像执行任何操作)。
zphenhs42#
你打算怎么处理这些图像?你真的需要imageicon示例,还是一个图像也可以?在这两种情况下,如果您使用imageio中的同步方法而不是imageicon构造函数,那么您可能更容易控制加载。
如果您在30张图像之后就遇到了outofmemoryerrors,我假设这些图像可能具有较高的分辨率和/或颜色深度,即使它们在磁盘上相对较小。加载图像时,图像将被解压缩,并且需要比压缩文件大得多的内存(对于彩色图像,通常为4宽度高度字节)。除非图像非常小,否则您可能无法在合理的内存量内缓存1500个未压缩的图像,因此您必须实现一些策略,仅加载当前需要的图像。
jfgube3f3#
正如tedil所说,您应该通过以下方式启动应用程序,为应用程序提供更多内存:
用“请等待”加载屏幕和进度条加载图像是很棘手的。它已经进入了高级挥杆领域。如果您使用的是Java6,我建议您阅读swingworker类。
下面的演示向您展示了一种方法:
zaq34kh64#
通过类加载器加载文件时应该非常小心,因为在类加载器处于活动状态时不会释放这些资源。
相反,使用另一种方法,使用java.io.file对象直接从磁盘加载文件。然后它们就可以被丢弃,而不会被看不见。
nvbavucw5#
如果您已经知道要加载多少个.png,您可能需要创建一个imageicon数组,并从一个或多个目录中逐个加载它们(这将允许您显示加载。。。屏幕)。
我认为您应该做的是在运行应用程序时增加jvm的最小/最大堆大小。您可以通过添加-xmx256m作为参数来指定它们(这会将最大堆设置为256mb)(也可能是-xms32m[这会将最小堆设置为32mb]),请参阅http://docs.sun.com/source/817-2180-10/pt_chap5.html#wp57033
您可以在启动应用程序时添加这些选项(例如“java-jar myapp.jar-xmx128m”),也可以添加到系统的jvm配置文件或项目的构建属性中。
这段代码将加载整个目录;如果您只想加载50个图像,只需摆弄start和stop参数。
如前所述,必须将最大堆(-xmx)设置为大约300m(例如分辨率1280x1024->1310720px->4字节/像素->5242880字节->50个图像->256mb)。