用小文件耗尽堆空间

时间:2017-04-19 18:34:09

标签: java memory-leaks bluej

我有一个游戏,它使用ArrayList来跟踪屏幕上的障碍物(从顶部流下来)。一旦它们到达底部,它们就会被移除。我有一个主类和一个障碍类。障碍包含一个方法,它将我的一个图像文件作为BufferedImage返回。图像文件不超过10K,有些小于1K。我知道我可以使用-Xmx来增加最大堆空间,但我认为这不是问题,因为文件非常小。我的想法是堆空间是为图像保留的,但是一旦不再使用它,那个空间仍然是保留的。我搜索了一下,发现Java有一个“垃圾收集器”,一旦图像不再使用,它​​应该可以释放堆空间。除了使用太大的文件外,还有一种称为“内存泄漏”的东西。这是一个非常简单的程序,我读到内存泄漏发生得很慢,但我通常会在一分钟内得到Java OutOfMemory Error: heap space。 在主类的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);
Obstacle类中的

getObsImg()方法:

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;
}

谢谢,我希望这个问题很受欢迎,因为如果不是,我可能会被阻止。我是java的新手,所以我会请你因此而放轻松。

1 个答案:

答案 0 :(得分:1)

  

我google了一下,发现Java有一个&#34;垃圾收集器&#34;一旦图像不再使用,这应该可以释放堆空间。

你需要做的不仅仅是谷歌#34;垃圾收集或GC是Java的基础,你必须更好地研究它。这不是一个可以撇去或懒惰的区域。

你了解什么&#34;不再使用&#34;是什么意思?

这意味着没有存在对象引用的地方。

问题#1是你的getObsImg方法直接操作实例变量obstacleImg,甚至可以到return obstacleImg;!该方法不应该引用外部变量,它应该分配一个局部变量并返回该变量。

将返回的值分配给实例变量是可以的。但是你必须控制对创建对象的引用,显然你还没有。

一旦您分配了对实例变量obstacleImg的引用,就无法收集对象(&#34; GCed&#34;),直到该变量被重新分配不同的值或其拥有Obstacle为止实例是&#34;不再使用&#34;。这意味着指向Obstacle的任何变量,数组或集合将使其保持活动状态以及其图像。

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

因此,寻找保持Obstacle活着的地方,包括通过容器,以及你可能保持图像活着的其他地方。不要通过直接分配外部变量来跨越范围。为了怜悯,研究范围和垃圾收集。