2012-01-03 243 views
0

我在做java中的Koch fractal snowflake并将其保存在svg文件中。分形和“java.lang.OutOfMemoryError:Java堆空间”

我正在用LineStrip2D类记忆分形(它是实现迭代的Vec2D的ArrayList的包装)。

主要功能是这一个:

public static LineStrip2D repeatPatternIntoLineStrip2D(
     LineStrip2D pattern, 
     LineStrip2D polygon, 
     boolean repeatUp) { 

    /* 
    * pattern: must be a pattern between Vec(0,0) and Vec(1,0) 
    *   (normalized beetween 0-1 and in X axis) 
    * */ 

    float angle, distance; 
    Vec2D pivot, a, b, direction, b1; 
    LineStrip2D new_polygon = new LineStrip2D(); 

    new_polygon.add(pattern.vertices.get(0)); 
    a = polygon.vertices.get(0); 

    int count=0; 
    for (int i = 1; i < polygon.vertices.size(); i++) { 
     b = polygon.vertices.get(i); 
     a = polygon.vertices.get(i-1); 

     distance = b.distanceTo(a); 
     direction = b.sub(a).normalize(); 
     angle = PApplet.atan2(direction.y, direction.x); 
     pivot = a; 

     for (int j = 1; j < pattern.vertices.size(); j++) { 
      Vec2D _b1 = pattern.vertices.get(j); 

      b1 = _b1.copy() ; 

      if(repeatUp)b1.y *= -1;    
      b1.scaleSelf(distance); 
      b1 = b1.rotate(angle); 
      b1.addSelf(pivot); 

      new_polygon.add(b1); 
      count++; 
     } 
     a = b; 
    } 
    System.out.println(count); 
    return new_polygon; 
} 

我有初始Koch曲线的模式:

enter image description here

我呼吁:

pattern = GeometryHelper.repeatPatternIntoLineStrip2D(pattern, pattern, false); 

现在的问题:

经过一些迭代(851968)我有一个java.lang.OutOfMemoryError:Java堆空间。 我该如何避免这个错误,并实现一个巨大的SVG文件? 我想我可以在各个步骤中完成这个过程,但我不明白如何以一种聪明的方式实现它。

回答

0

首先你为什么要使用变量count?您可以用System.out.println(polygon.vertices.size() * polygon.vertices.size());替换它并删除无用的操作,无缘无故递增count

为了您的内存不足的错误,建议您增加虚拟机

+0

我怀疑消除一个变量将解决他的堆大小问题。 – 2012-01-03 20:41:44

+1

我只是指他在代码 – 2012-01-03 20:51:41

+0

@ Jason482:+1中抵消-1的一些无用操作:答案是正确的,包含可能有用的附加信息,并且实际上是* first * correct回答(尽管比其他细节略少)。不值得downvote,恕我直言。 – Mac 2012-01-03 21:02:01

3

首先堆的大小,最简单的就是给JVM的内存。添加-Xmx = 1g可能就足够了(现在大多数机器都可以使用)。如果您需要更多,请随时添加更多内容,直到它超出您机器的可用范围。

这就是说,处理分形将始终是一个上限,你打内存使用。首先,您应该对应用程序进行配置以查看所有内存的使用情况。一旦你找到了,那么你可以考虑重新处理这个问题,使其更加友善。或者,您可以转向设计,在迭代之间迭代并保存结果到磁盘,以节省先前迭代的内存。

2

正如其他人所提到的,第一步是尝试通过修改JVM堆大小(它是命令行参数-Xmx = ...其中..)来实现您想要的迭代次数。 。是您希望分配的最大内存大小)。如果你的机器上有足够的内存,那么你可以设置得非常高(也许有办法让JVM使用磁盘交换空间,所以它可能非常高,但我不知道如何/如果这是可能的)。

如果这是不够的,那么你需要管理和序列化你自己的堆栈,你在迭代(非递归)实现中使用。这样看起来就是你将一个堆栈作为参数传递给你的函数,并且函数会从堆栈中读取它的参数(将它们留在堆栈上),然后在堆栈之前将参数写入堆栈(和当你达到你想要的最大深度时,你就会开始从堆栈中弹出数据)。迭代实现和堆栈管理是非平凡的,堆栈的序列化/持久性(随着堆栈大小的增加,需要管理自身以将部分存储到磁盘)。

+0

我在哪里可以找到如何在堆栈上实现序列化的一些解释? – nkint 2012-05-30 16:18:50

+0

我再次在这个项目上,这似乎是我可以实现的最佳解决方案。但我还没有完全理解它..没办法得到进一步的解释或例子? – nkint 2012-10-20 17:01:45

+0

@nkint你有什么设置你的堆大小?你的机器有多少RAM? – 2012-10-23 18:42:42

1

我认为这个问题与包装ArrayList的LineStrip2D类有关:该List实现后端是一个数组,其大小线性增长(如此处所述ArrayList: how does the size increase?)。 我相信你用尽内存,因为ArrayList分配一个全新的数组与新的大小,同时保留旧的(http://en.wikipedia.org/wiki/Dynamic_array)。因此,要完成绘图,您至少需要2 * MAX_SIZE。 您应该增加总堆数,但切换到LinkedList应该会改善情况。

相关问题