卡飞资源网

专业编程技术资源共享平台

JVM内存优化

Java面试题-jvm7垃圾收集器 Java面试题-jvm3 Java面试题-jvm1 Java面试题-jvm2 Java面试题-jvm5 Java面试题-jvm4 Java面试题-jvm6

你会估算GC频率吗?

正常情况我们应该根据我们的系统来进行一个内存的估算,这个我们可以在测试环境进行测试,最开始可以将内存设置的大一些,比如4G这样,当然这也可以根据业务系统估算来的。

比如从数据库获取一条数据占用128个字节,需要获取1000条数据,那么一次读取到内存的大小就是((128 B/1024 Kb/1024M)* 1000 = 0.122M,那么我们程序可能需要并发读取,比如每秒读取100次,那么内存占用就是0.122100 = 12.2M,如果堆内存设置1个G,那么年轻代大小大约就是333M,那么333M*80%/12.2M =21.84s,也就是说我们的程序几乎每分钟进行两到三次youngGC。这样可以让我们对系统有一个大致的估算。

内存优化

  • 内存分配

正常情况下不需要设置,那如果是促销或者秒杀的场景呢?

每台机器配置2c4G,以每秒3000笔订单为例,整个过程持续60秒

  • 内存溢出(OOM)

一般会有两个原因:

(1)大并发情况下

(2)内存泄露导致内存溢出

  • 大并发[秒杀]
  1. 浏览器缓存、本地缓存、验证码
  2. CDN静态资源服务器
  3. 集群+负载均衡
  4. 动静态资源分离、限流[基于令牌桶、漏桶算法]
  5. 应用级别缓存、接口防刷限流、队列、Tomcat性能优化
  6. 异步消息中间件
  7. Redis热点数据对象缓存
  8. 分布式锁、数据库锁
  9. 5分钟之内没有支付,取消订单、恢复库存等
  • 内存泄露导致内存溢出

ThreadLocal引起的内存泄露,最终导致内存溢出

public class TLController {
@RequestMapping(value = "/tl")
public String tl(HttpServletRequest request) {
  ThreadLocal<Byte[]> tl = new ThreadLocal<Byte[]>();
  // 1MB
  tl.set(new Byte[1024*1024]);
  return "ok";
}
}

(1)上传到服务器

jvm-case-0.0.1-SNAPSHOT.jar

(2)启动

java -jar -Xms1000M -Xmx1000M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=jvm.hprof  jvm-case-0.0.1-SNAPSHOT.jar

(3)使用jmeter模拟10000次并发

(4)top命令查看

top
top -Hp PID

(5)jstack查看线程情况,发现没有死锁或者IO阻塞的情况

jstack PID
java -jar arthas.jar   --->   thread

(6)查看堆内存的使用,发现堆内存的使用率已经高达88.95%

jmap -heap PID
java -jar arthas.jar   --->   dashboard

(7)此时可以大体判断出来,发生了内存泄露从而导致的内存溢出,那怎么排查呢?

jmap -histo:live PID | more
获取到jvm.hprof文件,上传到指定的工具分析,比如heaphero.io
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言