转载自http://blog.csdn.net/zmken497300/article/details/52496189

相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深入的认识。

在解决java内存溢出问题之前,需要对jvm(java虚拟机)的内存管理有一定的认识。jvm管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域)、Heap space(堆区域)、Java Stacks(Java栈)。其中永久保存区域主要存放Class(类)和Meta的信息,Class第一次被Load的时候被放入PermGen space区域,Class需要存储的内容主要包括方法和静态属性。堆区域用来存放Class的实例(即对象),对象需要存储的内容主要是非静态属性。每次用new创建一个对象实例后,对象实例存储在堆区域中,这部分空间也被jvm的垃圾回收机制管理。而Java栈跟大多数编程语言包括汇编语言的栈功能相似,主要基本类型变量以及方法的输入输出参数。Java程序的每个线程中都有一个独立的堆栈。容易发生内存溢出问题的内存空间包括:Permanent Generation space和Heap space。

第一种OutOfMemoryError: PermGen space

发生这种问题的原意是程序中使用了大量的jar或class,使java虚拟机装载类的空间不够,与Permanent Generation space有关。解决这类问题有以下两种办法:

  1. 增加java虚拟机中的XX:PermSize和XX:MaxPermSize参数的大小,其中XX:PermSize是初始永久保存区域大小,XX:MaxPermSize是最大永久保存区域大小。如针对tomcat6.0,在catalina.sh 或catalina.bat文件中一系列环境变量名说明结束处(大约在70行左右) 增加一行: JAVA_OPTS=" -XX:PermSize=64M -XX:MaxPermSize=128m" 如果是windows服务器还可以在系统环境变量中设置。感觉用tomcat发布sprint+struts+hibernate架构的程序时很容易发生这种内存溢出错误。使用上述方法,我成功解决了部署ssh项目的tomcat服务器经常宕机的问题。
  2. 清理应用程序中web-inf/lib下的jar,如果tomcat部署了多个应用,很多应用都使用了相同的jar,可以将共同的jar移到tomcat共同的lib下,减少类的重复加载。这种方法是网上部分人推荐的,我没试过,但感觉减少不了太大的空间,最靠谱的还是第一种方法。

第二种OutOfMemoryError:  Java heap space

发生这种问题的原因是java虚拟机创建的对象太多,在进行垃圾回收之间,虚拟机分配的到堆内存空间已经用满了,与Heap space有关。解决这类问题有两种思路:

  1. 检查程序,看是否有死循环或不必要地重复创建大量对象。找到原因后,修改程序和算法。 我以前写一个使用K-Means文本聚类算法对几万条文本记录(每条记录的特征向量大约10来个)进行文本聚类时,由于程序细节上有问题,就导致了Java heap space的内存溢出问题,后来通过修改程序得到了解决。
  2. 增加Java虚拟机中Xms(初始堆大小)和Xmx(最大堆大小)参数的大小。如:set JAVA_OPTS= -Xms256m -Xmx1024m

第三种OutOfMemoryError:unable to create new native thread

在java应用中,有时候会出现这样的错误:OutOfMemoryError: unable to create new native thread.这种怪事是因为JVM已经被系统分配了大量的内存(比如1.5G),并且它至少要占用可用内存的一半。有人发现,在线程个数很多的情况下,你分配给JVM的内存越多,那么,上述错误发生的可能性就越大。

那么是什么原因造成这种问题呢?

每一个32位的进程最多可以使用2G的可用内存,因为另外2G被操作系统保留。这里假设使用1.5G给JVM,那么还余下500M可用内存。这500M内存中的一部分必须用于系统dll的加载,那么真正剩下的也许只有400M,现在关键的地方出现了:当你使用Java创建一个线程,在JVM的内存里也会创建一个Thread对象,但是同时也会在操作系统里创建一个真正的物理线程(参考JVM规范),操作系统会在余下的400兆内存里创建这个物理线程,而不是在JVM的1500M的内存堆里创建。在jdk1.4里头,默认的栈大小是256KB,但是在jdk1.5里头,默认的栈大小为1M每线程,因此,在余下400M的可用内存里边我们最多也只能创建400个可用线程。

这样结论就出来了,要想创建更多的线程,你必须减少分配给JVM的最大内存。还有一种做法是让JVM宿主在你的JNI代码里边。

给出一个有关能够创建线程的最大个数的估算公式:

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

对于jdk1.5而言,假设操作系统保留120M内存:

1.5GB JVM: (2GB-1.5Gb-120MB)/(1MB) = ~380 threads 1.0GB JVM: (2GB-1.0Gb-120MB)/(1MB) = ~880 threads

对于栈大小为256KB的jdk1.4而言,

1.5GB allocated to JVM: ~1520 threads 1.0GB allocated to JVM: ~3520 threads 

对于这个异常我们首先需要判断下,发生内存溢出时进程中到底都有什么样的线程,这些线程是否是应该存在的,是否可以通过优化来降低线程数; 另外一方面默认情况下java为每个线程分配的栈内存大小是1M,通常情况下,这1M的栈内存空间是足足够用了,因为在通常在栈上存放的只是基础类型的数据或者对象的引用,这些东西都不会占据太大的内存, 我们可以通过调整jvm参数,降低为每个线程分配的栈内存大小来解决问题,例如在jvm参数中添加-Xss128k将线程栈内存大小设置为128k。

java中三种常见内存溢出错误的处理方法相关推荐

  1. java中三种常见内存溢出错误的处理方法(good)

    相信有一定java开发经验的人或多或少都会遇到OutOfMemoryError的问题,这个问题曾困扰了我很长时间,随着解决各类问题经验的积累以及对问题根源的探索,终于有了一个比较深入的认识. 在解决j ...

  2. 一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer

    一位面试官询问我:Java中的JVM内存溢出和内存泄露是什么?我这么回答成功拿到了offer. 墨眉无锋墨家代码 2020-11-22 20:16:50 10525 收藏 56 分类专栏: Java ...

  3. java调用dll报内存溢出错误或者程序崩溃

    因为业务需要,需要用Java去调用dll动态库来分析图片,结果调用后导致程序内存溢出,或者直接崩溃:再经过反复检查后,发现本身的我写的java代码并没有问题,最终去验证图片的时候: 1.图片访问不到, ...

  4. php流导出excel内存溢出,phpExcel导出大量数据出现内存溢出错误的解决方法

    phpExcel将读取的单元格信息保存在内存中,我们可以通过 复制代码代码如下: PHPExcel_Settings::setCacheStorageMethod() 来设置不同的缓存方式,已达到降低 ...

  5. java运行内存溢出指什么内存溢出_项目正常启动,但是在访问页面的时候java报内存溢出错误。。小感悟...

    先说一下背景,前两天由于本地的oracle数据库问题,导致项目启动数据库获取连接池错误,不能正常启动,折腾了一段时间,本地数据库整好了,想在本地把项目跑起来试试,把项目部署在tomcat正常启动,但是 ...

  6. Xamarin Android提示内存溢出错误

    Xamarin Android提示内存溢出错误 错误信息:java.lang.OutOfMemoryError, Consider increasing the value of $(JavaMaxi ...

  7. Tomcat启动报内存溢出错误解决(两种)

    1.绿色版Tomcat,启动报内存溢出错误:java.lang.OutOfMemoryError: PermGen space异常 找到D:\Tomcat-7\apache-tomcat-7.0.28 ...

  8. C#程序出现内存溢出错误的解决办法

    上周一个C#开发的站点出现了内存溢出错误:"引发类型为"System.OutOfMemoryException"的异常" 因为页面众多一时最初难以确定问题源,找 ...

  9. JAVA中堆栈和内存分配原理

    JAVA中堆栈和内存分配原理 1.栈.堆 1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在 ...

最新文章

  1. python numpy指定列最大值,统计次数
  2. boost::stacktrace::detail::void_ptr_cast相关的测试程序
  3. 转 carrer 之感
  4. SQLServer创建数据库详解
  5. react 日历组件_anujs1.5.1支持React.Suspense与lazy
  6. 第三届蓝桥杯省赛---第39级台阶
  7. exoplayer 纯java,Exoplayer不播放任何视频
  8. Shell编程进阶 1.3data命令
  9. 《奠基计算机网络》2011年8月15日出版 视频下载 http://www.91xueit.com
  10. 漫谈LiteOS之开发板-串口(基于GD32450i-EVAL)
  11. 谷歌修复又一枚遭在野利用的 Chrome 0day
  12. Visual Stadio 2012创建WebApplication应用和运行赏析
  13. 解决速达软件提示将numeric转换为数据类型numeric时发生算术溢出错误问题
  14. Type-c与micro usb 的对应关系
  15. 音乐标签修改 android,音乐标签Android版
  16. 怎样花两年时间去面试一个人
  17. 十分钟快速入门 Pandas
  18. 推荐收藏 | 常用图片处理网站合集(8个网站)
  19. 2021年度济南职工医保门统定点医疗机构名单
  20. 视频播放器(二)——播放列表

热门文章

  1. 勒索病毒傀儡进程脱壳
  2. PyCairo 后端
  3. IntelliJ IDEA不好用?那是因为没掌握这些技巧
  4. 分布式事务之底层原理揭秘
  5. Docker 部署不香吗?
  6. 关于GiF动图你不知道的9件事
  7. H.265在QRTC场景的落地运用
  8. 写代码之前应该做的几件事
  9. Bing搜索核心技术BitFunnel原理
  10. 教育机构如何提升在线教育技术能力? | 云+社区技术沙龙