从容器的自动kill理解java程序的内存使用
- 一、操作系统的oom kill
- 二、java程序的oom error
- 三、java的内存构成
- 1、Heap
- 2、Class
- 3、Thread
- 4、Code
- 5、GC
- 6、DirectMemory
- 7、SHR
引发操作系统对进程进行oom kill的原因:
1、当ram与swap耗尽,操作系统选择低优先级、耗用ram最多的进程进行kill
2、进程占用的ram超出cgroup的限制,如docker就是利用cgroup限制可用的系统资源
查看系统诊断日志,确认近期是否发生oom kill:
dmesg -T二、java程序的oom error
java自身对内存进行分区管理,任何一个区域的使用超出限制,都会引发oom error,生成dump并退出程序;如:老生代里长期不释放的类实例、metaspace加载太多类定义、DirectMemory放太多缓冲数据。
三、java的内存构成为避免oom kill和oom error,需要了解java占用的内存构成,保证每个区域设置了合适的上限,且总大小不超过ram/cgroup的限制。
top命令看到的RES值,即进程实际使用的内存,java进程的RES主要由以下部分构成:
堆内存,放置未释放的类实例,新老生代共用,由-Xmx或-XX:MaxRAMPercentage设置最大值,默认值是1/4的当前ram或1/4的cgroup最大限制
2、Class放置类定义,用-XX:MaxMetaspaceSize设置最大值,默认无限制
3、Thread放置stack,即stackoverflow里的stack
4、Code放置JIT字节码运行时编译成的机器码;如果使用Janino等在线编译工具,要释放类实例和classloader后,才能回收类定义和机器码占用的内存
5、GC辅助运行GC逻辑需要使用的内存
6、DirectMemory主要放置直接提供给操作系统的网络IO接口使用的缓冲数据,用-XX:MaxDirectMemorySize设置最大值,默认为heap最大值的85%
7、SHR共享库/文件占用的内存;如:操作memory-mapped file来与操作系统的存储IO接口交互
要统计前5类构成,需在启动参数里加入-XX:NativeMemoryTracking=summary,查看命令:
jcmdVM.native_memory summary scale=MB
SHR,使用top命令直接查看
DirectMemory,使用RES - SHR - Native Memory 可得(RES是包含SHR的)



