背景:在cmd窗口输入命令运行某一个jar文件(即Java的API应用程序),出现上述StackOverflowError问题。
原因:字面理解即是堆栈的内存不够分配了,出现了溢出。更详细清楚的解释可以参见StackOverFlowError:原因和解决方案
上面的博文给出的解决方案有两个:
1.修改源代码
修改源代码,找出产生“ StackOverflowError”的地方(如非终止的递归调用),进行修改。由于不是本人自己写的代码,所以这条不太适应。如果想要查看jar源码,可以采用eclipse查看。
2. 增加线程堆栈大小
这条更为实用,可以使用JVM的各种参数对启动应用程序的线程增加内存。这里面涉及到堆栈内存的各种指标,主要包括如下:
- Xms:JVM初始堆内存大小
- Xmx:JVM堆内存的最大值
- Xmn:JVM中新生代大小
- Xss:JVM每个线程的大小
- XX:PermSize:永久代大小
- XX:MaxPermSize:永久代最大值
其中后两个参数在JDK8.0版本中不存在了。关于参数的解释可以参见JVM核心参数图解,稍微一看就明白。
举个实际例子,参考java 线程栈大小配置,jvm之栈、堆,jvm默认栈空间大小部分内容,命令java -Xmx3072 -Xms3072M -Xmn2048M -Xss1M
的意思是:
-Xmx3072M:设置JVM最大可用内存为3072M。
-Xms3072M:设置JVM初始内存为3072M。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2048M:设置年轻代大小为2G。增大年轻代后,将会减小年老代大小。不过此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss1M:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。
3. 解决方案小结
简单来讲,如果一开始的命令是java -jar my_cap.jar
,那么修改成为java -jar -Xmx5120m -Xms5120m -Xmn2560m -Xss10m my_cap.jar
即可,具体内存分配可以多测试几次就知道了(只要不出现错误提示即可)。更多详细的内存分配机制可以稍加搜索了解一下。
参考资料:
StackOverFlowError:原因和解决方案
JVM核心参数图解
java 线程栈大小配置,jvm之栈、堆,jvm默认栈空间大小
网友评论