美文网首页
调优案例分析三【堆外内存导致的溢出错误】

调优案例分析三【堆外内存导致的溢出错误】

作者: 云芈山人 | 来源:发表于2021-07-13 23:29 被阅读0次

案例出于《深入理解Java虚拟机》第二版

场景

一个学校的小型项目:基于B/S的电子考试系统,为了实现客户端能实时地从服务器接收考试数据,系统使用了逆向AJAX技术(也称Comet或者Server Side Push),选用CometD1.1.1作为服务端推送框架,服务器是Jetty7.1.4,硬件为一台普通PC机,Core i5 CPU,4GB 内存,运行32位Windows操作系统。

问题

  • 测试期间发现服务端不定时抛出内存溢出异常,网站管理员尝试过把堆开到最大,而32位系统最多到1.6GB就基本无法再加大了,且开大基本没效果,抛出内存溢出异常好像更频繁。
  • 加入-XX:+HeapDumpOnOutOfMemoryError,也没反应,抛出内存溢出异常时什么文件都没有发生。
  • 通过jstat发现GC并不频繁,Eden区、Survivor区、老年代以及永久代内存全部都无问题,但是仍然不停抛出内存溢出异常。

分析

  • 系统日志中找到异常堆栈
    [org.eclipse.jetty.util.log] handle failed java.lang.OutOfMemoryError:null
  • 操作系统对每个进程能管理的内存是有限制的,这台服务器使用的32位Windows平台的限制是2GB,其中划了1.6GB给Java堆,而Direct Memory内存并不算入1.6GB的堆之内,因此它最大也只能在剩余的0.4GB空间中分出一部分。
  • 此应用中导致内存溢出的关键:垃圾收集进行时,虚拟机虽会对Direct Memory 进行回收,但Direct Memory却不能像新生代、老年代那样,发现空间不足就通知收集器进行垃圾回收,它只能等老年代满了后Full GC,然后“顺便” 帮它清理内存的废弃对象。否则它只能一直等到抛出内存溢出异常时,先catch,再在catch块里面:System.gc()!
  • 若虚拟机无动作(如打开了-XX:+DisableExplicitGC开关),则即使堆中仍有许多空间内存,却不得不抛出内存溢出异常。
  • 而本案例中CometD1.1.1框架,正好有大量的NIO操作需要使用到Direct Memory 内存。

经验

从实践经验的角度出发,除Java堆和永久代之外,我们注意到下面这些区域还会占用较多的内存,这里所有的内存总和受到操作系统进程最大内存的限制。

  1. Direct Memory:可通过-XX:MaxDirectMemorySize调整大小,内存不足时抛出OutOfMemoryError或者OutOfMemoryError:Direct buffer memory。
  2. 线程堆栈:可通过-Xss调整大小,内存不足时抛出StackOverflowError(纵向无法分配,即无法分配新的栈帧)或者OutOfMemoryError:unable to create new native thread(横向无法分配,即无法建立新的线程)。
  3. Socket缓存区:每个Socket连接都Receive和Send两个缓存区,分别占大约37KB和25KB内存,连接多的话这块内存占用也比较可观。如果无法分配,则可能会抛出IOException:Too many open files异常。
  4. JNI代码:如果代码中使用JNI调用本地库,那本地库使用的内存也不在堆中。
  5. 虚拟机和GC:虚拟机、GC的代码执行也要消耗一定的内存。

相关文章

  • 调优案例分析三【堆外内存导致的溢出错误】

    案例出于《深入理解Java虚拟机》第二版 场景 一个学校的小型项目:基于B/S的电子考试系统,为了实现客户端能实时...

  • JVM 案例 - 堆外内存导致的溢出错误

    案例 一个网站为了实现客户端实时从服务端接收数据,使用了 CometD 1.1.1 作为服务端推送框架,服务器是 ...

  • 【026】2020.11.26 周四 JVM调优案例-02

    JVM调优案例 11.26 集群间同步导致的内存溢出 问题 一个B/S的MISS系统开启JBossCache全局缓...

  • JVM-GC调优

    零、本文纲要 一、 GC调优基本思路二、 新生代内存调优三、 老年代内存调优四、 GC调优案例 官方GC调优指南[...

  • 2020互联网Java后端面试专题解析—JVM21题

    前言 文章对 JVM 内存区域分布、JVM 内存溢出分析、JVM 垃圾回收算法/垃圾收集器、JVM 性能调优工具及...

  • Java OutOfMemoryError 宕机实验

    概述 JVM OutOfMemoryError(OOME,内存溢出错误)导致宕机的情况有多种,此处主要以超出堆最大...

  • Java内存溢出

    Java内存溢出 堆溢出 大量对象占据了堆空间,而且这些对象是强引用,导致无法回收 直接内存溢出 Java的NIO...

  • 2.1 自动内存管理

    1.Java内存区域与内存溢出异常 2.垃圾收集器与内存分配策略 3.虚拟机性能监控、故障处理工具 4.调优案例分...

  • 内存溢出的原因分析及调优

    JVM在抛出java.lang.OutOfMemoryError时,除了会打印出一行描述信息,还会打印堆栈跟踪,因...

  • JVM内存调优&GC

    调优最主要的调优方式: 堆大小设置。 回收器选择。1、内存调优的时候要更多地使用JDK提供的内存查看工具,比如JC...

网友评论

      本文标题:调优案例分析三【堆外内存导致的溢出错误】

      本文链接:https://www.haomeiwen.com/subject/vklepltx.html