JVM如果发生的伯父的8种原因,你能及时想出解决的方法吗

  

小:xx服务又宕机了

小B:歪日,咋搞的,登上去看看咋回事

小答:又伯父了,不知道哪个* *写的代码,一坨*一样。


 JVM如果发生的伯父的8种原因,你能及时想出解决的方法吗



撸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种原因,你能及时想出解决的方法吗