Java 使用小文件耗尽堆空间

Java 使用小文件耗尽堆空间,java,memory-leaks,bluej,Java,Memory Leaks,Bluej,我有一个游戏,使用ArrayList跟踪屏幕上从顶部向下流动的障碍物。一旦它们到达底部,就会被移除。我有一门主课和一门障碍课。障碍物包含一个方法,该方法将我的一个图像文件作为BuffereImage返回。图像文件不超过10K,有些小于1K。我知道我可以使用-Xmx来增加最大堆空间,但我认为这不是问题所在,因为文件非常小。我的想法是,堆空间是为映像保留的,但一旦不再使用,该空间仍然保留。我在谷歌上搜索了一下,发现Java有一个垃圾收集器,一旦映像不再使用,它应该会释放堆空间。除了使用过大的文件外,

我有一个游戏,使用ArrayList跟踪屏幕上从顶部向下流动的障碍物。一旦它们到达底部,就会被移除。我有一门主课和一门障碍课。障碍物包含一个方法,该方法将我的一个图像文件作为BuffereImage返回。图像文件不超过10K,有些小于1K。我知道我可以使用-Xmx来增加最大堆空间,但我认为这不是问题所在,因为文件非常小。我的想法是,堆空间是为映像保留的,但一旦不再使用,该空间仍然保留。我在谷歌上搜索了一下,发现Java有一个垃圾收集器,一旦映像不再使用,它应该会释放堆空间。除了使用过大的文件外,还有一种称为内存泄漏的情况。这是一个非常简单的程序,据我所知,内存泄漏发生得很慢,但我得到了Java OutOfMemory错误:堆空间通常在一分钟内。 在主类的while循环中:

JLabel freshObsLabel = null;
   for (int i = 0; i < obsList.size(); i++) //looping through list of obstacles
   {
       freshObsLabel = new JLabel(new ImageIcon(obsList.get(i).getObsImg())); //error occurs on call to getObsImg()
       frame.getContentPane().add(freshObsLabel);
   
谢谢,我希望这个问题能得到大家的好评,否则我可能会被屏蔽。我对java非常陌生,所以我想请你对我放轻松,因为这一点

我在谷歌上搜索了一下,发现Java有一个垃圾收集器,一旦映像不再使用,它应该会释放堆空间

你需要做的不仅仅是谷歌。垃圾收集,或称GC,是Java的基础,您最好彻底研究它。这不是一个可以略读或懒惰的领域

你明白不再使用的意思是什么吗

这意味着没有对对象的引用存在的位置

问题1是getObsImg方法直接操作实例变量obstacleImg,甚至返回obstacleImg;!方法不应该以这种方式引用外部变量,它应该分配一个局部变量并返回该变量

可以将返回值赋给实例变量。但您必须控制对已创建对象的引用,因为您显然还没有

将引用分配给实例变量obstacleImg后,在重新分配该变量的其他值或其所属的障碍物实例不再使用之前,无法收集对象。这意味着任何指向障碍物的变量、数组或集合都将使它及其映像保持活动状态

同样,如果您愚蠢地将obstacleImg值指定给任何其他变量或容器的元素,那么该其他引用将保持图像的活动状态,直到所有此类引用都被重新指定、超出范围,或者所有对其包含对象的引用都这样做


因此,请查找使障碍物保持活动状态的位置,包括通过容器的位置,以及可能使图像保持活动状态的其他位置。不要通过直接分配给外部变量来跨越范围。出于同情,请研究范围和垃圾收集。

我可以看到您将标签+图像添加到内容窗格中。但是你会移除它们吗?还有,你迭代过的障碍列表有多大?我总共使用了3张图片,但是有很多障碍。障碍列表开始时为空,但每3秒添加一个新障碍。障碍物以每0.75秒1个像素的速度在屏幕上向下移动,当它们到达底部1500像素时,它们将从列表中删除。列表中没有积累太多的障碍,也没有一个使用非常大的文件,所以我不认为所有的堆空间都会被使用。我不打算浏览或懒惰,我只是以前不熟悉GC,因为我已经很久没有使用Java了,也没有意识到它的重要性。我真的是Java的初学者,不知道出于同情我需要研究作用域和垃圾收集。你是否建议我使用一个临时变量返回,然后将obstacleImg设置为null?有些事情对我来说有点超前,我想我还没有完全理解。不要生气,内特。我说了一个,不是你。这是工程,不是鸡尾酒会。让我们暂时放弃这个词。方法不应返回外部变量。它应该使用局部变量。当您研究范围时,就会更清楚在本例中本地引用是如何在方法的右括号中消失的。这少了一个混淆GC分析的参考。
String obsImgDirectory;
BufferedImage obstacleImg;
public BufferedImage getObsImg() //gets BufferedImage corresponding to keyword given in constructor
{
    obsImgDirectory = obstacleType + "Obs.jpg";
    try {
        obstacleImg = ImageIO.read(new File(obsImgDirectory)); //line on which the error occurs
    } catch (IOException e) {
        System.out.println("'" + obsImgDirectory + "' could not be read or '" + obstacleType + "' is an invalid obstacle type.");
        e.getStackTrace();}
    return obstacleImg;
}