https://zhuanlan.zhihu.com/p/423000502
这篇文章来说说和PhantomReference
/finalize
无关的东西 - MALLOC_ARENA_MAX
. 这个东西只对Linux里的Java有用, 如果你在Linux上有内存耗尽(OOM, out of memory)的问题, 可以先调试一下MALLOC_ARENA_MAX
看.
MALLOC_ARENA_MAX
?MALLOC_ARENA_MAX
是一个Linux环境变量, 用于控制提供给glibc
的内存池的数量. 默认是 8 * CPU核的数量. 用法是在命令行里输入:
export MALLOC_ARENA_MAX=2
glibc
又是什么?glibc
是Java的默认原生内存分配器(default native memory allocator).
glibc
和我又有什么关系?为了提升内存效率, glibc
分配出来内存的objects可能不会被返还给操作系统.
好处: 这样可以重复使用这些内存
坏处: 造成很多内存碎片
潜在问题: 这些内存碎片会无限制的增长最后导致内存耗尽(OOM)
参考: https://github.com/prestodb/presto/issues/8993
默认情况glibc
会给每个线程提供一个新的128MB的"malloc arena"(是有上限的, 默认最多是8*处理器数量).
这个对于只有少量线程但是需要大量并行内存空间的情况是有好处的, 但是对于使用JVM堆外内存/原生内存的线程没好处. 因为分配的"malloc arena"也用不上, 它要用的是堆外的内存.
潜在问题: 虚拟内存大增. 对于有ulimit
限制的程序, 在容器里的云应用, 嵌入式, 都需要小心调试MALLOC_ARENA_MAX
, 试着减少它的数字.
参考: https://bugs.openjdk.java.net/browse/JDK-8193521
MALLOC_ARENA_MAX
?一般来说, 调试MALLOC_ARENA_MAX
的数字就是在效率和内存消耗之间做选择. 使用默认的MALLOC_ARENA_MAX
能获得最佳效率, 但是可能消耗更多的内存. 减少MALLOC_ARENA_MAX
能减少内存使用, 但是效率可能稍微低一些.
通常我们把MALLOC_ARENA_MAX
设为2或者4能达到比较好的效果同时不会有内存问题.
项目实例: 我们这边有一个比较大的Java项目一直把MALLOC_ARENA_MAX
设为2, 否则就会内存不够用.