美国上市公司,专注Java培训21年

Java中的OutOfMemoryError


导读:今天在群里有个哥们称“不连sjdbc不会把内存吃光,连sjdbc跑一会就把内存吃光”,倍感诧异,我们已经用sj很久了,一直未发现sj吃内存的情况,遂向他要了测试程序。测试之后才发现他所谓的吃内存是报了“java.lang.OutOfMemoryError: unable to create new native thread”的错,殊不知创建线程不使用JVM Memory,这个报错不是程序吃内存,跟sjdbc更是没有关系。他的数据库连接池maxActive=30,开线程较多时(我开了10000个),前面的线程没有释放数据库连接,后面的线程就要等待,造成线程积压,最终无法创建新线程,自然“unable to create new native thread”。所以还需要扫盲式的向诸位普及一下Java中的内存溢出

Java中的OutOfMemoryError

1.java.lang.OutOfMemoryError: unable to create new native thread

就是上面例子里面提到的情况。Java中当你创建线程的时候,JVM会在JVM 内存创建一个Thread同时创建一个系统本地线程,这个系统线程使用的内存不是JVM memory,而是系统剩余的内存,所以遇到这种情况有时候需要通过“减少内存”的手段来解决(指减少堆内存)。通常情况下我们有个计算公式来估算能创建线程数的多少:countOfThreads=(processMaxMemory - JVM Memory - otherOsMemory) / (threadStackSize) ,这里的MaxProcessMemory是指一个进程可以占用的最大内存,比如在32位window下是2G,otherOsMemory是保留的操作系统内存,threadStackSize是通过-Xss参数设置的线程栈大小,当然,还会受到系统最大可创建的线程数量的限制。

2.Java.lang.OutOfMemoryError: Java heap space

这种是我们最常见的Java堆溢出,我们配置JVM参数时使用-Xms配置堆的最小值,使用-Xmx配置堆的最大值(通常会将-Xms和-Xmx配置成相同,避免堆的自动扩展)。Java堆中存放的是对象实例,当Java堆中对象达到限制就会产生内存溢出,常见的情况有:死循环往一个List中添加对象,一次性将大文件或者从数据库查询的大批量数据加载到内存中。对于这种情况,我们通过JVM配置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Data/domains/trans-account/server1/logs来保存内存快照,然后用相关内存分析工具进行分析。

3. java.lang.OutOfMemoryError: PermGen space

PermGen space的全称是Permanent Generation space,是内存的永久保存区域,主要存储虚拟机加载的类、常量、静态变量等元数据信息,垃圾收集行为在这个区域几乎不出现。对于有大量JSP、大量使用CGLib字节码增强的应用,会很容易出现这种错误,出现问题时,我们经常通过增大-XX:MaxPermSize参数来解决。

4. java.lang.OutOfMemoryError: GC overhead limit exceeded

GC overhead limt exceed检查是Hotspot VM定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。”这种情况跟第二种情况有重合的地方,也是通过检查是否有死循环或者占用大内存的代码,当然,可以使用-XX:-UseGCOverheadLimit(默认是+UseGCOverheadLimit)来去除GC时间的限制。

5. java.lang.OutOfMemoryError: nativeGetNewTLA

这个错误只有在JRockit的JVM上才会遇到,大家工作环境中如果都默认使用Hotspot的话应该不会遇到这个问题,所以如果大家不感兴趣完全可以不care(真的,私以为,没有业务场景基础的技术意淫都是耍流氓)。TLA是Thread Local Area(线程本地空间)的简写,线程本地空间是多线程程序里面为了更有效的进行内存分配而建立的缓存。每一个线程都有一份自己的缓存,当这个线程要创建对象的时候,就在这上面分配。如果你有很多线程同时并发,又要创建大量的对象,可能会出现这个问题。

6.java.lang.OutOfMemoryError: Requested array size exceeds VM limit

这个错误比较少见,除非你真的new了一个非常非常大的数组(比如,一个亿?YOU CAN TRY~)当出现这种情况,与其去增大JVM的-Xmx,不如好好看下你的代码逻辑是不是出现了什么问题。

7.java.lang.OutOfMemoryError: request xxxxxx(size) bytes for xxxxxxx(reason). Out of swap space?

额,这种情况我真没遇到过,不过我们可以了解一下:它是当虚拟机向本地操作系统申请内存失败时抛出的。这和你用完了堆或者持久化中的内存的情况有些不同。这个错误通常是在你的程序已经逼近平台限制的时候产生的。这个信息告诉你的是你可能已经用光了物理内存以及虚拟内存了。由于虚拟内存通常是用磁盘作为交换分区,因此你最先想到的解决方法可能是先增加交换分区的大小。

8.java.lang.OutOfMemoryError: xxxx xxxx(Native method)

这种报错是从native method中抛出的,不是JVM执行的方法,如果遇到这种情况,咳,自求多福吧。

感谢大家阅读由java培训机构分享的“Java中的OutOfMemoryError”希望本教程对大家有所帮助,更多精彩内容请关注Java培训官网

免责声明:本文由小编转载自网络,旨在分享提供阅读,版权归原作者所有,如有侵权请联系我们进行删除


【免责声明】本文部分系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,如涉及作品内容、版权和其它问题,请在30日内与我们联系,我们会予以重改或删除相关文章,以保证您的权益!

Java开发高端课程免费试学

大咖讲师+项目实战全面提升你的职场竞争力

  • 海量实战教程
  • 1V1答疑解惑
  • 行业动态分析
  • 大神学习路径图

相关推荐

更多

Java开班时间

收起