java线程运行也是需要内存空间的,-Xss参数指定每个线程堆栈的大小,为jvm启动的每个线程分配的内存大小。在jdk1.4版本中是256K,JDK1.5及以上版本是1M。
tomcat jvm的参数设置如下:
JAVA_OPTS=%JAVA_OPTS% -server -Xms1024m -Xmx1024m -Xmn200M -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=1 -Xss256k已经通过-Xss设置每个java线程堆栈的大小为256K。
在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
当需要创建线程,而操作系统剩余内存不够分配给一个java线程时,就会报Out of Memory Error的错误。
由于已经设置通过-Xss设置java线程栈的大小为256K,因此也决定不采用这个解决方案。
现在只剩 下Decrease Java heap size (-Xmx/-Xms) 这个解决方案了。通过减少堆的大小,而留出足够的内存空间给java线程堆栈使用。
32位的window操作系统给每个进程分配的内存空间是2G,减去堆的最大容量和PermSize的最大容量,剩下的容量就留给java线程栈使用。
经过分析代码和之前错误的日志,发现一般在350个线程这样就出现Out of Memory Error的错误。
在出现错误时,heap空间才用了不到40%。因此决定将java heap的从1G减少到768M。
修改的jvm参数如下:
JAVA_OPTS=%JAVA_OPTS% -server -Xms768m -Xmx768m -Xmn200M -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=1 -Xss256k到目前为止,系统已经稳定运行1个月,各个参数指标都在正常范围内。heap使用率最高才70%。
总结:
1、经过这次解决bug,加深了对java虚拟机的了解,特别是线程栈,内存堆,持久代,新生代等概念。
2、一定要仔细阅读日志文件,一步一步排除掉潜在的解决方案。综合系统的运行环境,找出合理的解决方案。