文章目录

测试环境中突然发生这种错误

运行内存发生了溢出

Tomcat下catalina.sh下配置的JAVA_OPTS定义了运行的相关内存等设置

JAVA_OPTS="-Xms400m -Xmx400m -Xss1024K -XX:PermSize=64m -XX:MaxPermSize=128m"

这些设置参数的意思:

-Xmx400m:设置jvm最大可用内存为400M。

-Xms400m:设置Jvm促使内存为400m,此值可以设置与-Xmx相同,以避免每次垃圾回收完成后jvm重新分配内存。

-Xss1024K:设置每个线程堆栈大小。jdk5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进行内的线程数还是有限制的,不能无限生成,经验是在3000~5000左右。

-XX:PermSize=64m:jvm出事分配的非堆内存

-XX:MaxPermSize=128m:设置jvm最大允许分配的非堆内存,按需分配。

后来我问运维人员,给了我一份设置让我替换

JAVA_OPTS="-server -Dfile.encoding=UTF-8 -Xms1024m -Xmx2048m -XX:NewSize=512m -XX:MaxNewSize=1024m -XX:SurvivorRatio=64 -XX:PermSize=512m -XX:MaxPermSize=1024m"

将相关参数的大小设置大了。之后就没有出现问题,不过我感觉按说是相关的代码存在问题,要不然为什么之前没有产生呢。

我在网上找了个看了看总结:

产生java.lang.OutOfMemoryError这个错误的原因大都出去:JVM内存过小、程序不严密,从而产生了过多的垃圾。

导致OutOfMemoryError异常的常见原因有以下几种:

  • 内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
  • 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
  • 代码中存在死循环或循环产生过多重复的对象实体;
  • 使用的第三方软件中的BUG;
  • 启动参数内存值设定的过小;

常见的错误提示: - tomcat:java.lang.OutOfMemoryError: PermGen space - tomcat:java.lang.OutOfMemoryError: Java heap space - weblogic:Root cause of ServletException - java.lang.OutOfMemoryError - resin:java.lang.OutOfMemoryError - java:java.lang.OutOfMemoryError

解决相关问题主要是增加jvm的内存大小,还有就是优化代码,释放垃圾

优化代码:

主要包括避免死循环,应该及时释放种资源:内存,数据库的各种连接,防止一次载入太多的数据。导致java.lang.OutMemoryError的根本原因是程序不健壮。因此,从根本上解决Java内存溢出的唯一方法是修改程序,及时地释放没用的对象,释放内存空间。遇到该错误的时候一定要仔细检查程序。

Java代码导致OutOfMemoryError错误的解决:

需要重点排查的几点:

  • 检查代码中是否有死循环或递归调用。
  • 检查是否有大循环重复产生新对象实体。
  • 检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询
  • 检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

《深入理解Java虚拟机..》书中2.4章节说到了相关的错误和之后的解决 问题。