Java优化以防止堆空间内存不足

时间:2014-01-20 10:42:20

标签: java optimization out-of-memory heap heap-size

好的,我在某个特定情况下遇到问题,我的程序从堆空间中得到内存不足错误。

假设我们有两个ArrayList,第一个包含许多T个对象,第二个包含从第一个List的W个对象创建的T个对象。

我们以这种方式循环它(在循环之后列表:

public void funct(ArrayList<T> list)
{
  ArrayList<W> list2 = new ArrayList<W>();
  for (int i = 0 ; i < list.size() ; i++)
  {
     W temp = new W();
     temp.set(list.get(i));
     temp.saveToDB();
     list2.add(temp);          
  }

  // more code! from this point on the `list` is useless
}

我的代码与此代码非常相似,但是当list包含大量对象时,我经常会从内存中获取堆空间(在for循环期间),我想解决这个问题。

我不太清楚GC如何在java中工作,但在前面的例子中肯定有很多可能的优化。 由于在for循环后list不再使用,我认为首先优化从for loop更改为do loop并在我们循环时清空list

public void funct(ArrayList<T> list)
{
  ArrayList<W> list2 = new ArrayList<W>();
  while (list.size() > 0)
  {
     W temp = new W();
     temp.set(list.remove(0));
     temp.saveToDB();
     list2.add(temp);
  }

  // more code! from this point on the `list` is useless
}

这种修改有用吗? 如何更好地优化上述代码?以及如何防止堆空间内存错误? (不可能增加XMXXMS值。

4 个答案:

答案 0 :(得分:1)

这取决于很多事情。 W和T物体有多大? 你可以肯定做的一个优化是ArrayList list2 = new ArrayList(list.size()); 这样,您的listarray不需要多次调整其大小。 这不会有太大的差异。真正的问题可能是你的W和T物体的大小和数量。您是否考虑过使用不同的数据结构来管理较小部分的对象?

答案 1 :(得分:1)

您可以尝试设置-XX:MaxNewSize=40% of you Xmx-XX:NewSize=40% of you Xmx 此参数将加速GC调用,因为您的创建率很高。

如需更多帮助,请查看here

答案 2 :(得分:1)

如果您进行了一些内存分析,您会发现最大的耗尽源是W个实例,您可以通过将它们添加到list2来保留这些实例。 ArrayList本身为每个包含的对象增加了一个非常小的开销(如果正确预先调整大小只有4个字节,最差情况下为8个字节),所以即使你保留list,这也无关紧要。

如果不改变您在循环中创建的每个W实例的非保留方法,您将无法减轻堆压力。

答案 3 :(得分:0)

您继续引用原始列表中的所有项目:

temp.set(list.get(i)) // you probably store somewhere the passed reference

如果T对象的大小很大而且你不需要它的所有字段,请尝试使用它的投影。

temp.set( extractWhatINeed( list.get(i) ) )

这将涉及创建一个字段少于T的新类(提取方法的返回类型)。

现在,当您不引用原始项目时,它们符合GC的条件(当列表本身不再被引用时)。