JVM的OOM分为多种状况,下面会针对java.lang.OutOfMemoryError:Javaheapspace这种状况解说一下产生的原因与解决方案。
在JAVA运用启动时,会限制运用的运用空间。也就说,任何一个JAVA运用,都只能运用有限的内存空间。
JAVA的内存空间在JDK7及曾经划分为堆与永久代。在JDK8之后移除了永久代,选用元空间来代替。
在启动时,经过指定JVM参数:`-Xmx`来设置可运用的最大堆巨细。假如没有显式的设置,则体系上默认为物理内存的1/4(根据物理内存的不同状况有不同的分配规则。可是遍及能够认为是1/4)。
产生java.lang.OutOfMemoryError:Javaheapspace异常时,代表着运用测验从堆上请求一个区域时,堆没有可配的空间。(注:可能有可运用的物理内存,可是没有已经达到了JAVA运用可分配的内存巨细)
JVM是很智能的,在即将产生OOM时,会进行一次FullGC以收回可收回的目标来开释空间。假如FullGC之后仍是没有可满足巨细的空间分配,才抛出java.lang.OutOfMemoryError:Javaheapspace。
java.lang.OutOfMemoryError:Javaheapspace正常是怎么产生的呢?
突发高峰期:程序在正常的用户量和必定数据量时运行正常。可是,在某个高峰时导致超出预期阈值,内存存活目标运用空间的量超出最大堆,并且无法收回。内存走漏:由于编程错误导致运用程序不再需求的目标(数据)一直被持有引证,导致无法被收回。随着时刻的推移,走漏的内存目标占用了一切的可用堆空间。分配合理的足够内存
最简略的解决方法就给JVM分配足够大的内存来满足运行程序的需求。
可是,需求注意在内存泄漏的状况下,分配再大的内存也只是推迟了java.lang.OutOfMemoryError:Javaheapspace的产生。
并且,加大了JVM堆内存,也会增加在GC时的暂停时刻(STW),影响程序的吞吐量,增加推迟。
怎么分配一个合理的内存空间,是需求针对GC进行优化的。也就是常说的JVM调优。JVM调优能够参考:「JVM」GC——调优介绍
那么,怎么调整经过分配JAVA堆空间来解决问题呢?
首先,需求了解以下这些问题:
哪些目标占用了很多的堆空间在哪些代码中创建了这些目标上述的问题能够经过JVM自身的jmap来dump出运行时的仓库信息。然后经过如:MAT,JProfiler,jconsole等空间来进行内存目标占用的跟踪。
MAT运用能够参考:[JVM]MAT进阶运用
当然,这种方法是比较原始的方法。建议经过如:Plumbr等JVM监控工具来跟踪问题。
Plumbr的陈述信息
以上图的监控举例扼要阐明一下怎么适当的进行堆空间的巨细分配。
上图所示中,能够得到如下信息:
一切相关目标的整个GCRoot引证内存消耗最多的目标:
这些目标在代码中的分配位置:
根据上述的信息,咱们能够得到这样的猜想:
这个程序的需求的运行空间超过248MB,并且是无法在必定时刻内开释被收回。那么,按JVM调优的思路,建议分配的最大堆巨细为:老时代活跃数据巨细*3~4倍。
所以,咱们第一次调整时,能够分配:248*4=992。
由于堆巨细的无法承认,所以第一次调整直接调整为:-Xmx1024m。
java内存溢出的几种原因和解决方案是什么?
java内存溢出的几种原因和解决方案如下。
第一种类型的内存溢出也被认为是最多的。第一个反应认为是内存溢出。仓库溢出。
什么状况是仓库溢出呢?当我看到下一个关键词时,鲤鱼山水充满了堆叠。
Java.lang.outofmemoryerror:javaheapspace.
也就是说,当鲤鱼山水看到heap关联时,一定会溢出仓库。此刻,假如代码没有问题,适当调整-Xmx和-Xms就能够防止,但一定是代码没有问题的前提。为什么会溢出来?代码有问题,或许拜访次数太多,每次拜访的时刻太长,或许数据太多,无法开释数据。因为垃圾收回器会发现它们是垃圾收回器,因此在此处出现不认为是这些东西的主意之前,体系可能会事先陈述过错的关键字。
ava.lang.outofmemoryerror3360gcoverheadlimitexceeded
假如体系处于高频GC状况,并且收回效果仍然很差,这将开端陈述此过错。在这种状况下,一般来说,可能会产生许多不应开释的目标。这是因为引证运用不当和大型目标请求导致的,但javaheapspace内存溢出可能不会提早陈述此过错。这意味着内存不足是直接原因,可能不是高频GC。
类型2的内存溢出、PermGen溢出或PermGen已满的提示,能够看到类似以下内容的关键字:
重要的信息是:
Java.lang.outofmemoryerror:permgenspace
原因:体系代码十分多、引证的第三方十分多、代码中运用了很多常量、在内部注入常量、动态代码加载等办法导致常量池膨胀。JDK1.5今后能够通过设置收回永久谱带,这里不做GC也足够了,所以一般本年很少做同样的操作,所以面对这种状况常常运用
类型3的内存溢出:在运用ByteBuffer的allocateDirect()()时运用,在许多javaNIO结构中将其封装为单独的办法
溢出关键字:
Java.lang.outofmemoryerror:directbuffermemory
假如直接或直接运用ByteBuffer的allocateDirect办法,假如不运用clear,则会出现同样的问题。一般的参考程序IO输出包括直接内存和非直接内存对应的内核状况和用户状况的转化进程。一般的APP使用要将文件内容输出到客户端,需求通过OS的直接内存转化复制到程序的非直接内存,也就是heap直接内存由操作体系和APP使用程序一起办理,直接内存不是APP使用程序能够直接控制的内存。请注意,jvm垃圾收回不会直接收回内存部分的内存。
假如有十分相似的操作,请考虑设置参数。-XX:MaxDirectMemorySize
类型4内存溢出过错:
溢出关键字:
java.lang.StackOverflowError
此参数直接表明-Xss太小。我请求了许多本地调用的仓库引脚等内容存储在用户现在具有的线程中。在jdk1.4之前,线程缺省为256K,在1.5之后为1M。假如陈述这个过错,只能说明-Xss太小了。当然,一些制造商的JVM不是这个参数。本文只针对HotspotVM。可是,您能够根据需求优化体系,以使-Xss的值可用。
第五类内存溢出过错:
溢出关键字:
Java.lang.outofmemoryerror3360unabletocreatenewnativethread
上面第4个溢出过错,说明晰线程的内存区域,但实际上线程基本上只占用了heap以外的内存区域。也就是说,该过错表明在heap以外的区域中,不能向线程分配内存区域。这解释了是内存本身不够,仍是把heap的区域设定得太大,剩余的内存变少了,仍是线程本身因为占用内存而不够了,其理由
第6类内存溢出:
溢出关键字
Java.lang.outofmemoryerror3360request{}bytefor{}outofswap
出现这种过错一般是因为地址空间不足。
六种常见的溢出显现了99%的JVM溢出。摆脱这些溢出是十分困难的。可是,除非产生十分古怪的毛病,例如物理内存硬件问题导致codecache过错,否则在这种状况下内存会直接落入crash中。同样,内存也能够转化为nativecode。因为乱用JNI会导致无法开释本地内存的问题,因此请尽量防止运用JNI。ioexception:toomanyon也会导致套接字连接数据打开过多
广州天河区珠江新城富力盈力大厦北塔2706
020-38013166(网站咨询专线)
400-001-5281 (售后服务热线)
深圳市坂田十二橡树庄园F1-7栋
Site/ http://www.szciya.com
E-mail/ itciya@vip.163.com
品牌服务专线:400-001-5281
长沙市天心区芙蓉中路三段398号新时空大厦5楼
联系电话/ (+86 0731)88282200
品牌服务专线/ 400-966-8830
旗下运营网站:
Copyright © 2016 广州思洋文化传播有限公司,保留所有权利。 粤ICP备09033321号