在我的java Web应用程序中,我有一个后台工作线程,它需要大量的堆栈空间,因为它使用activiti工作流引擎和groovy脚本任务运行一个非常复杂的工作流。
目前,我需要在64位Java和Tomcat上将JVM Xss设置高达16MB,以规避任何StackOverflowErrors。如果发生错误,堆栈跟踪真的很大(几百行),但这一切都发生在引擎内部,所以我无法对它做任何事情。
现在我的问题是:有没有办法在运行时增加单个线程的堆栈大小?
我想将应用程序中所有线程的JVM默认Xss设置降低到512k,我知道这已经足够,只能运行16M的worker。
Java API为Thread类的构造函数提供了有关此主题的一些信息:
public Thread(ThreadGroup group,
Runnable target,
String name,
long stackSize)
但它提到,行为不能保证([1])并且我没有找到任何信息,如果它可以在Windows上工作。
另外,如果一个线程的堆栈空间不能增加而且我必须指定16MB作为默认值,那么设置如此高的后果会是什么?这是否意味着每个新线程在初始化时将保留16MB内存(即200个线程* 16MB:3,2 GB)?
据我所知,从jconsole和taskmgr可以看出,自Xss设置增加以来,内存占用似乎没有太大变化,但也许我错过了一些东西。
任何帮助或澄清将不胜感激。
[1]:http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#Thread(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String,long)
答案 0 :(得分:4)
HotSpot上的-Xss
指定最大大小,而不是它将使用的大小。使用的大小基于使用情况,因此如果您指定这个不合理的大,它将浪费虚拟内存(这可能是32位JVM上的问题),但它不会浪费物理内存。如果你有一个64位的JVM,那么制作你想要任何线程的最大值是没有什么不利的。
另外,如果一个线程的堆栈空间不能增加而且我必须指定16MB作为默认值,那么设置如此高的后果会是什么?这是否意味着每个新线程在初始化时将保留16MB内存(即200个线程* 16MB:3,2 GB)?
每个线程都将使用这么多虚拟内存。在32位JVM上,即使实际使用的内存非常少,也会耗尽地址空间。在64位JVM上,您的限制在TB中,只有实际使用的堆栈才会使用主内存。
答案 1 :(得分:0)
如果相关线程非常耗费流程。将此Thread的逻辑实现为另一个应用程序,并使用队列传递信息和流程变量。 您可以根据需要增加此应用程序的内存参数。
来自文档链接:
虚拟机可以自由地将stackSize参数视为a 建议。如果指定的值不合理地低 平台,虚拟机可能会使用某些特定于平台的 最小值;如果指定的值不合理地高,则 虚拟机可能会使用某些特定于平台的最大值。 同样,虚拟机可以自由地舍入指定的值 或者看起来合适(或完全忽略它)。