如何增加堆栈大小以允许更多递归?

How to increase stack size to allow more recursion?

我是运行在处理递归方法,但是当作业太大的时候,报错:

crashed in event thread due to Timeout occurred while waiting for packet 139.

但是当递归很小的时候就可以了。对于更大的递归问题,有没有办法增加堆栈?

这是我的代码,用于在屏幕上绘制图形。它适用于小数字,但不适用于大数字。

boolean pit;
int xc;
int yc;
color negro;
color rojo;
color c;
long tiempoI;
long tiempoF;
long espera;
void setup(){
  size(500,500);
  negro=color(0,0,0);
  negro=color(0,0,0);
  rojo=#FF0000;
  pit=false;
  tiempoI=millis();
  tiempoF=millis();
  espera=5;
}
void draw(){
  background(240);
  noSmooth();
  //dibujarRectangulo(0,0,300,300);
  rect(0,0,100,100);
  if(pit){
    pintar(xc,yc);
  }
}
void mousePressed() {
  xc=mouseX;
  yc=mouseY;
  pit=true;
  loadPixels();
  c=pixels[xc+(width*yc)];
  println(red(c)+" "+green(c)+" "+blue(c));


}
public void pintar(int x,int y){
  if(x<width&&x>0&&y<height&&y>0){
    stroke(rojo);
    c=get(x,y);
    if(c!=rojo&&c!=negro){
      point(x,y);
    }
    c=get(x+1,y);
    if(c!=rojo&&c!=negro){
      pintar(x+1,y);
    }

    c=get(x-1,y);
    if(c!=rojo&&c!=negro){
      pintar(x-1,y);
    }

    c=get(x,y+1);
    if(c!=rojo&&c!=negro){
      pintar(x,y+1);
    }

    c=get(x,y-1);
    if(c!=rojo&&c!=negro  ){
      pintar(x,y-1);
    }

  }
}

回溯:

crashed in event thread due to Timeout occurred while waiting for packet 139. org.eclipse.jdi.TimeoutException: Timeout occurred while waiting for packet 139. at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:186) at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:197) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:191) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:226) at org.eclipse.jdi.internal.ThreadReferenceImpl.frames(ThreadReferenceImpl.java:257) at org.eclipse.jdi.internal.ThreadReferenceImpl.frames(ThreadReferenceImpl.java:240) at processing.mode.java.runner.Runner.findException(Runner.java:888) at processing.mode.java.runner.Runner.reportException(Runner.java:871) at processing.mode.java.runner.Runner.exceptionEvent(Runner.java:797) at processing.mode.java.runner.Runner.run(Runner.java:688) org.eclipse.jdi.TimeoutException: Timeout occurred while waiting for packet 140. at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:186) at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:197) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:191) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:226) at org.eclipse.jdi.internal.VirtualMachineImpl.exit(VirtualMachineImpl.java:716) at processing.mode.java.runner.Runner.close(Runner.java:961) at processing.mode.java.JavaEditor.handleStop(JavaEditor.java:728) at processing.mode.java.JavaToolbar.handlePressed(JavaToolbar.java:96) at processing.app.EditorToolbar.mousePressed(EditorToolbar.java:474) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access0(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) org.eclipse.jdi.TimeoutException: Timeout occurred while waiting for packet 141. at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:186) at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:197) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:191) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:226) at org.eclipse.jdi.internal.VirtualMachineImpl.exit(VirtualMachineImpl.java:716) at processing.mode.java.runner.Runner.close(Runner.java:961) at processing.mode.java.JavaEditor.handleStop(JavaEditor.java:728) at processing.mode.java.JavaToolbar.handlePressed(JavaToolbar.java:96) at processing.app.EditorToolbar.mousePressed(EditorToolbar.java:474) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access0(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) org.eclipse.jdi.TimeoutException: Timeout occurred while waiting for packet 142. at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:186) at org.eclipse.jdi.internal.connect.PacketReceiveManager.getReply(PacketReceiveManager.java:197) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:191) at org.eclipse.jdi.internal.MirrorImpl.requestVM(MirrorImpl.java:226) at org.eclipse.jdi.internal.VirtualMachineImpl.exit(VirtualMachineImpl.java:716) at processing.mode.java.runner.Runner.close(Runner.java:961) at processing.mode.java.JavaEditor.handleStop(JavaEditor.java:728) at processing.mode.java.JavaToolbar.handlePressed(JavaToolbar.java:96) at processing.app.EditorToolbar.mousePressed(EditorToolbar.java:474) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access0(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.awt.EventQueue.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)

您可能在收到 Whosebug 异常之前达到了递归调用的最大数量。我建议在 Java 控制面板中更改堆 space 大小。

  1. Go to the Control Panel in Windows.
  2. Click on Java.
  3. Go to the Java tab and click on View.
  4. You will see a section called Runtime Parameters. Double click on that column (make sure you double click on the version you are currently using). This will allow you to edit it.
  5. There are a few ways to set your heap size. I will list them:

      -Xms<size>        set initial Java heap size
    
      -Xmx<size>        set maximum Java heap size
    
      -Xss<size>        set java thread stack size
    
  6. As an example, I have set mine to: -Xms512m. Don't forget to Apply/Save the changes made.

对于Eclipse,还可以设置堆space:

  1. In Run->Run Configuration find the Name of the class you have been running, select it, click the Arguments tab then add: -Xms512M -Xmx1524M to the VM Arguments section

递归时可能会超出堆栈。你的树不应该太深。看到一些考虑 .

但是,根据您提供的堆栈跟踪和代码,问题不在这部分代码中。根据堆栈跟踪,看起来您递归调用了一些 GUI 方法或鼠标事件处理方法,而不是 pintar() 方法。

它可能只是速度慢。从 100 x 100 图像变为 500 x 500 图像会将像素数从 10,000 增加到 250,000。这是一个很大的飞跃。而且您的递归方法最终将对每个像素进行多次调用。这可能会使事情陷入困境。

要查看是否是这种情况,请尝试逐渐增加图像大小,并在图像大小增加时计算程序所需的时间。您可以预计 500x500 版本所花的时间是 100x100 版本的 25 倍。这对你来说是合理的执行时间吗?

如果是这样的性能问题,请查看是否可以将其切换为迭代实现,并可能将 stroke() 调用提升到循环之外。

还要注意 draw() 是在循环内调用的,除非你用 noLoop()redraw() 控制它。你可能想在这里做。您的 draw() 在较大的图像上可能足够慢,以至于它不能 运行 在其分配的时间片内,并且 draw() 调用和事件处理正在得到备份。

您的错误确实是由过多的递归引起的 Whosebug,但处理过程中会用您看到的奇怪错误来弥补这一点。关于该错误的文档是 here.

您可以增加 Java 堆栈大小以增加递归调用的限制。可以找到信息 here,但要点是您必须在 运行 时将 -Xss 设置传递到 Java。

但是,该设置要求您 运行 您的草图作为 Java 应用程序。这是可能的,但它涉及将草图导出为 jar,然后 运行 通过命令提示符打开 jar,或切换到 eclipse。这比简单地点击 Processing 中的 运行 按钮要多得多 - 而且您发送 jar 的任何用户都必须做同样的事情。

相反,您可能应该重构您的算法以消除过多的递归。