小:xx服务又宕机了
小B:歪日,咋搞的,登上去看看咋回事
小答:又伯父了,不知道哪个* *写的代码,一坨*一样。
撸Java的同学,多多少少会碰到内存溢出(伯父)的场景,但造成伯父的原因却是多种多样。
这种场景最为常见,报错信息:
. lang。OutOfMemoryError: Java堆空间
1,代码中可能存在大对象分配
2,可能存在内存泄露,导致在多次GC之后,还是无法找到一块足够大的内存容纳当前对象。
1,检查是否存在大对象的分配,最有可能的是大数组分配
2,通过jmap命令,把堆内存转储下来,使用垫工具分析一下,检查是否存在内存泄露的问题
3,如果没有找到明显的内存泄露,使用- xmx加大堆内存
4,还有一点容易被忽略,检查是否有大量的自定义的可终结对象,也有可能是框架内部提供的,考虑其存在的必要性
报错信息:
. lang。OutOfMemoryError: PermGen空间 . lang。OutOfMemoryError: Metaspace
永久代是HotSot虚拟机对方法区的具体实现,存放了被虚拟机加载的类信息,常量、静态变量,JIT编译后的代码等。
JDK8后,元空间替换了永久代,元空间使用的是本地内存,还有其它细节变化:
- <李>
字符串常量由永久代转移到堆中
李> <李>和永久代相关的JVM参数已移除
李>可能原因有如下几种:
1,在Java7之前,频繁的错误使用String.intern()方法
2,运行期间生成了大量的代理类,导致方法区被撑爆,无法卸载
3,应用长时间运行,没有重启
没有重启JVM进程一般发生在调试时,如下面tomcat官网的一个常见问题:
为什么内存使用量增加,当我重新部署一个web应用程序?
这是因为web应用程序有内存泄漏。
一个常见的问题是“PermGen”内存泄漏。他们发生,因为类加载器(和它加载的类对象)不能被回收,除非一些需求得到满足()。它们存储在永久的JVM堆的一代,当你重新部署创建一个新的类加载器,所有这些类的加载另一个副本。这可能会导致最终OufOfMemoryErrors。
(*)的要求是,所有这类装载器装载的类应该能够被gc在同一时间。
引用>
因为该伯父原因比较简单,解决方法有如下几种:
1,检查是否永久代空间或者元空间设置的过小
2,检查代码中是否存在大量的反射操作
3,转储之后通过垫检查是否存在大量由于反射生成的代理类
4,放大招,重启JVM
这个异常比较的罕见,报错信息:
. lang。OutOfMemoryError: GC开销限制超过
这个是JDK6新加的错误类型,一般都是堆太小导致的.Sun官方对此的定义:超过98%的时间用来做GC并且回收了不到2%的堆内存时会抛出此异常。
1,检查项目中是否有大量的死循环或有使用大内存的代码,优化代码。
2,添加参数- xx: -UseGCOverheadLimit禁用这个检查,其实这个参数解决不了内存问题,只是把错误的信息延后,最终出现. lang。OutOfMemoryError: Java堆空间。
3,转储内存,检查是否存在内存泄露,如果没有,加大内存。
报错信息:
. lang。OutOfMemoryError:无法创建新的本地线程
出现这种异常,基本上都是创建的了大量的线程导致的,以前碰到过一次,通过jstack出来一共8000多个线程。
1,通过xss降低的每个线程栈大小的容量
2,线程总数也受到系统空闲内存和操作系统的限制,检查是否该系统下有此限制:
<李>
/proc/sys/kernel/pid_max
李> <李>/proc/sys/kernel/thread-max
李> <李>maxuserprocess (ulimit - u)
李> <李>/proc/sys/vm/maxmapcount
李>
下面这些伯父异常,可能大部分的同学都没有碰到过,但还是需要了解一下
报错信息:
. lang。VM OutOfMemoryError:要求数组大小超过限制这种情况一般是由于不合理的数组分配请求导致的,在为数组分配内存之前,JVM会执行一项检查。要分配的数组在该平台是否可以寻址(可寻址),如果不能寻址(可寻址)就会抛出这个错误。
JVM如果发生的伯父的8种原因,你能及时想出解决的方法吗