JVM系列之OOM(七)

OOM包路径:java.lang.object——>java.lang.Throwable——>java.lang.error—— >java.lang.VirtualMachineError——>java.lang.OutOfMemoryError

java.lang.StackOverflowError

栈溢出,深度的方法调用会导致栈溢出,线程请求的栈深度大于虚拟机所允许的深度

java.lang.OutOfMemoryError:Java heap space

堆内存溢出 对象多,新建大对象

java.lang.OutOfMemoryError:GC overhead limit exceeded

GC回收时间过长时会抛出OutOfMemroyError。

过长定义:超过98%的时间用来做GC并且回收了不到2%的堆内存,连续多次GC都只回收了不到2%的极端情况下才会抛出。

假如不抛出 GC overhead limit 错误的话,GC清理出来的这么点内存很快会再次集满,追使GC再次执行,这样就形成恶性循环;CPU使用率一直是100%,GC却没有任何成果

java.lang.OutOfMemoryError:Direct buffer memory

直接内存:不是运行时内存区域的一部分,但被频繁使用,1.4引入NIO概念,在新的nio类(基于通道(Channel)与缓冲区 (Buffer)的I/O方式),它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的 DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。不受堆的大小限制,但受物理机总内存(包括物理内存、SWAP分区或者分页文件)大小以及处理器寻址空间的限制。

异常:如果在配置虚拟机-Xmx等参数时,忽略了直接内存,使得各个内存区域总和大于物理内存限制,从而导致动态扩展时出现OOM

ByteBuffer.allocate(capability) 第一种方式是分配JVM堆内存,属于GC管辖范围,由于需要拷贝所以速度相对较慢

BvteBuffer.allocteDirect(capability) 第一种方式是分配OS本地内存,不属于GC管辖范围,由于不需要内存拷贝所以速度相对较快

但如果不断分配本地内存,堆内存很少使用,那么JVM就不需要执行GC,DirectByteBuffer对象就不会被回收,这时候堆内存充足,但本地内存可能已经使用光了,再次尝试分配本地内存就会出现OutOfMemoryError,那程序就直接崩溃了

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

高并发请求服务器时会出现

导致原因:

应用创建了太多的线程,超过系统承载极限,服务器并不允许一个应用程序创建这么多线程,linux系统默认允许单个进程可以创建的线程数是1024个,当应用创建超过这个数量,就会java.lang.OutOfMemoryError: unable to create new native thread

解决办法:

想办法降低应用程序创建的线程数量,分析应用是否真的需要创建这么多线程,如果不是,修改代码将线程数降到最低。若应用确实需要创建很多线程,远超过Linux系统的默认1024个线程的限制,可以通过修改Linux服务器配置,扩大Linux默认限制。

linux调整线程数

su z3
ulimit -u
vim /etc/security/limits.d/90-nproc.conf

java.lang.OutOfMemoryError:Metaspace

元空间溢出,不断生成类往元空间灌,类占据的空间总是会超过Metaspace指定的空间大小

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值