IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> JVM实战:调优案例分析 -> 正文阅读

[Java知识库]JVM实战:调优案例分析

请添加图片描述

请求延迟导致内存溢出

《从零开始带你成为JVM实战高手》
在这里插入图片描述

Exception in thread "http-nio-8080-exec-1089" java.lang.OutOfMemoryError: Java heap space

http-nio-8080-exec-1089说的就是tomcat的工作线程

发现占据内存最大的就是大量的byte[]数组,一大堆byte[]数组占据了大约8g左右的内存空间,给Tomcat应用分配的堆内存也就是8G左右

这些数组被哪个类引用?

org.apache.tomcat.util.threads.TaskThread
byte[10008192] @ 0x7aa800000 GET /order/v2 HTTP/1.0-forward...
byte[10008192] @ 0x7aa800000 GET /order/v2 HTTP/1.0-forward...
byte[10008192] @ 0x7aa800000 GET /order/v2 HTTP/1.0-forward...
byte[10008192] @ 0x7aa800000 GET /order/v2 HTTP/1.0-forward...

MAT中可以查看具体有哪些内存存在,Tomcat的工作线程大致有400个左右,每个Tomcat线程会创建2个byte[]数组,每个byte[]数组是10MB左右

400个工作线程同时在处理请求,结果创建出来了8G内存的byte[]数组,进而导致内存溢出。

系统每秒的qps是100,并不是400。

每个请求处理完毕需要4s时间

为什么Tomcat工作线程在处理一个请求时会创建2个10MB的数组

max-http-header-size: 10000000

为什么一个请求需要4s?

Timeout Exception....

通过rpc调用时出现了大量的请求超时,超时时间是4s

超时时间设为1s。每秒100个请求过来,只有200个数组,占据2g内存,远不会把内存塞满,然后1秒内这100个请求全部超时,请求就处理结束了

适当调小 max-http-header-size 参数

堆外内存溢出

nio handle failed java.lang.OutOfMemoryError: Direct buffer memory
at org.eclipse.jetty.io.nio.xxxx
at org.eclipse.jetty.io.nio.xxxx
at org.eclipse.jetty.io.nio.xxxx

堆外内存如何申请和释放?

在Java代码中使用堆外内存,是使用DirectByteBuffer类,这个类本身是在JVM堆内存里的,但是在创建这个对象的同时,会在堆外内存中划出一块内存空间和这个对象关联起来
在这里插入图片描述
为什么会出现堆外内存溢出?

当创建了很多DirectByteBuffer对象,占用了大量的堆外内存,这些DirectByteBuffer对象没有GC线程来回收,就不会释放堆外内存。当堆外内存被大量的DirectByteBuffer对象关联使用了,当没有堆外内存还继续申请堆外内存时,就会报内存溢出

内存分配不合理,给了年轻代100mb的空间,老年代反而给了700mb的空间,进而导致Survivor只有10MB左右的空间

在 young gc 过后,一些存活下来的对象(包括一些DirectByteBuffer在内)会超过10mb,没法放入Survivor中,直接进入老年代。这样老年代中的DirectByteBuffer会越来越多,其实这些老年代中的DirectByteBuffer很多都是可以回收状态,但是因为老年代一直没塞满,没有触发full gc,自然就不会回收老年代里的DirectByteBuffer,导致堆外内存一直无法回收,最终导致堆外内存溢出

Java NIO没有考虑过这个问题吗?

其实这种问题Java NIO是考虑到的,它每次分配新的堆外内存的时候,都会调用System.gc()去提醒JVM主动执行gc去回收掉没人引用的DirectByteBuffer对象,释放堆外内存空间。

但是我们在JVM中设置了如下参数

-XX:+DisableExplicitGC

导致System.gc()不生效

解决方案:合理分配内存,让年轻代有更多内存,将参数该为-XX:-DisableExplicitGC,让System.gc()生效

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-12 17:18:07  更:2022-03-12 17:22:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 8:47:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码