2012-01-03 461 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應該會改善情況。

相關問題