Linux - 记一次某Java程序启动报错(申请内存失败)

在这里插入图片描述


问题

启动的时候直接抛出如下异常

Native memory allocation (mmap) failed to map 2879048192 bytes for committing reserved memory

在 Linux 上部署项目时遇到 Native memory allocation (mmap) failed to map 2879048192 bytes for committing reserved memory 错误,这通常表明系统在尝试分配内存时遇到了问题。虽然 free 命令显示有足够的可用内存,并且 ulimit -a 显示内存没有被限制,但仍可能有其他原因导致该问题。


可能原因分析

可能原因分析

  1. 内存碎片化

    • 尽管 free 显示有足够的可用内存,但这些内存可能不是连续的。mmap 需要分配连续的内存块,如果内存碎片化严重,可能无法找到足够大的连续内存块。
  2. 地址空间不足

    • 32 位系统的虚拟地址空间有限,即使物理内存充足,虚拟地址空间也可能不足。
    • 64 位系统通常不太可能出现这个问题,但在极端情况下(例如,系统运行多个内存密集型应用程序)也可能发生。
  3. 内核参数限制

    • 某些内核参数(如 vm.max_map_countvm.overcommit_memory)可能限制了内存分配。
  4. 容器或虚拟机限制

    • 如果在 Docker 容器或虚拟机中运行应用程序,容器或虚拟机本身可能有内存限制。

尝试各种解决方案

  1. 检查内存碎片化

    • 使用 cat /proc/meminfo 查看内存详细信息。
    • 重点关注 MemFreeMemAvailableHugePages_TotalHugePages_Free
    • 使用 sudo sysctl -a | grep vm.min_free_kbytes 确认内核保留的最小空闲内存。
  2. 调整内核参数

    • vm.max_map_count:最大 mmap 区域数。
      sudo sysctl -w vm.max_map_count=262144
      
    • vm.overcommit_memory:内存过度提交策略。 【我们通过调整参数,临时修复了该问题
      sudo sysctl -w vm.overcommit_memory=1
      
  3. 检查虚拟地址空间

    • 确保系统运行在 64 位模式下。
    • 检查应用程序是否有特定的内存限制。
  4. 检查容器/虚拟机限制

    • 对于 Docker 容器:
      docker inspect <container_id> | grep Memory
      
    • 对于虚拟机,检查虚拟机管理工具的内存设置。

尝试解决过程

  1. 检查内存详细信息:

    cat /proc/meminfo
    
  2. 检查内核参数:

    sudo sysctl -a | grep vm
    
  3. 调整内核参数:

    sudo sysctl -w vm.max_map_count=262144
    sudo sysctl -w vm.overcommit_memory=1
    
  4. 检查 Docker 容器内存设置:

    docker inspect <container_id> | grep Memory
    
    

解决办法: 调整 overcommit_meory参数

调整 overcommit_meory参数
在这里插入图片描述


overcommit_memory详解

在 Linux 操作系统中,内存分配是一个关键的任务。内存的高效使用和管理直接影响系统的性能和稳定性。overcommit_memory 是一个重要的内核参数,用于控制内存分配策略。

什么是 overcommit_memory

overcommit_memory 是 Linux 内核中的一个参数,通过 /proc/sys/vm/overcommit_memory 文件进行配置。它决定了内核如何处理内存分配请求,尤其是在可用物理内存不足的情况下。

overcommit_memory 的选项及其含义

overcommit_memory 参数有三个可能的值,每个值对应一种特定的内存分配策略:

  1. 0 - 启发式内存分配(默认值)

    • 内核根据一定的启发式算法决定是否允许内存分配请求。内核会考虑当前的内存使用情况和预期的内存需求,通常会允许合理范围内的内存过度分配。
    • 优点:灵活性较高,适合大多数应用场景。
    • 缺点:可能在内存非常紧张时导致 OOM(Out Of Memory)错误。
  2. 1 - 总是允许内存分配

    • 内核允许所有内存分配请求,无论当前的内存使用情况如何。这意味着即使系统内存已经耗尽,内核也会继续分配内存。
    • 优点:极大的灵活性,确保所有内存分配请求都能成功。
    • 缺点:可能导致严重的内存不足问题,甚至导致系统崩溃。
  3. 2 - 禁止过度分配

    • 内核严格限制内存分配,只有在有足够的物理内存和交换空间时才允许内存分配请求。这个策略会结合 overcommit_ratio 参数来确定可用的内存总量。
    • 优点:提高系统稳定性,防止 OOM 错误。
    • 缺点:降低内存分配灵活性,可能拒绝一些合理的内存分配请求。

配置 overcommit_memory

可以通过以下命令查看和设置 overcommit_memory 参数:

查看当前设置

cat /proc/sys/vm/overcommit_memory

设置 overcommit_memory

例如,将 overcommit_memory 设置为 1:

echo 1 > /proc/sys/vm/overcommit_memory

配置 overcommit_ratio

如果 overcommit_memory 设置为 2,还需要配置 overcommit_ratio 参数来决定可用内存总量。overcommit_ratio 是一个百分比值,表示可分配的物理内存和交换空间的比例。

echo 50 > /proc/sys/vm/overcommit_ratio

这个配置表示内核允许分配的内存总量为物理内存加上 50% 的交换空间。

参数设置对系统的影响

启发式内存分配(0)

这种设置平衡了灵活性和稳定性,适合大多数应用场景。系统会尝试合理地分配内存,防止过度分配,但在极端情况下可能仍会遇到 OOM 错误。

总是允许内存分配(1)

这种设置提供了最大的灵活性,但也伴随着最高的风险。适用于需要极大内存灵活性的场景,如高性能计算或科学计算,但需注意可能的内存不足问题。

禁止过度分配(2)

这种设置提供了最大的稳定性,适用于需要严格内存控制的场景,如数据库服务器或关键业务应用。通过合理设置 overcommit_ratio,可以确保系统不会因内存不足而崩溃。

实例与使用建议

数据库服务器

对于数据库服务器,建议使用禁止过度分配的策略(设置 overcommit_memory 为 2),并合理配置 overcommit_ratio 以确保稳定性。例如,对于一个拥有 16GB 内存和 8GB 交换空间的系统,可以将 overcommit_ratio 设置为 50:

echo 2 > /proc/sys/vm/overcommit_memory
echo 50 > /proc/sys/vm/overcommit_ratio

高性能计算应用

对于高性能计算应用,可以考虑启用总是允许内存分配的策略(设置 overcommit_memory 为 1),以确保所有内存分配请求都能成功:

echo 1 > /proc/sys/vm/overcommit_memory

RedHat官网调优指南 (临时或永久改变系统的内存管理行为)

https://docs.redhat.com/zh_hans/documentation/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-captun

在 Linux 上,调整内存相关参数可以临时或永久改变系统的内存管理行为。

临时调整内存参数

临时调整内存参数可以通过向 /proc/sys 文件系统中的相应文件写入值来实现。这种方法在系统重启后会失效,需要重新设置。

  1. 调整 overcommit_memory 参数

    echo 1 > /proc/sys/vm/overcommit_memory
    
  2. 调整 overcommit_ratio 参数

    echo 50 > /proc/sys/vm/overcommit_ratio
    
  3. 调整 max_map_count 参数

    echo 262144 > /proc/sys/vm/max_map_count
    
  4. 调整 nr_hugepages 参数

    echo 128 > /proc/sys/vm/nr_hugepages
    
  5. 调整其他相关参数

    echo 65536 > /proc/sys/kernel/msgmax
    echo 65536 > /proc/sys/kernel/msgmnb
    echo 1985 > /proc/sys/kernel/msgmni
    echo 4294967296 > /proc/sys/kernel/shmall
    echo 68719476736 > /proc/sys/kernel/shmmax
    echo 4096 > /proc/sys/kernel/shmmni
    echo 32768 > /proc/sys/kernel/threads-max
    echo 65536 > /proc/sys/fs/aio-max-nr
    echo 1048576 > /proc/sys/fs/file-max
    

永久调整内存参数

为了使内存参数的调整在系统重启后依然有效,可以将这些设置写入 /etc/sysctl.conf 文件,或在 /etc/sysctl.d/ 目录下创建一个新的配置文件。

  1. 编辑 /etc/sysctl.conf 文件

    sudo nano /etc/sysctl.conf
    

    添加以下内容:

    vm.overcommit_memory = 1
    vm.overcommit_ratio = 50
    vm.max_map_count = 262144
    vm.nr_hugepages = 128
    kernel.msgmax = 65536
    kernel.msgmnb = 65536
    kernel.msgmni = 1985
    kernel.shmall = 4294967296
    kernel.shmmax = 68719476736
    kernel.shmmni = 4096
    kernel.threads-max = 32768
    fs.aio-max-nr = 65536
    fs.file-max = 1048576
    
  2. 创建新的配置文件(例如 /etc/sysctl.d/99-custom.conf

    sudo nano /etc/sysctl.d/99-custom.conf
    

    添加相同的内容:

    vm.overcommit_memory = 1
    vm.overcommit_ratio = 50
    vm.max_map_count = 262144
    vm.nr_hugepages = 128
    kernel.msgmax = 65536
    kernel.msgmnb = 65536
    kernel.msgmni = 1985
    kernel.shmall = 4294967296
    kernel.shmmax = 68719476736
    kernel.shmmni = 4096
    kernel.threads-max = 32768
    fs.aio-max-nr = 65536
    fs.file-max = 1048576
    
  3. 应用配置

    sudo sysctl -p
    

参考命令

  • 临时调整参数

    echo 1 > /proc/sys/vm/overcommit_memory
    echo 262144 > /proc/sys/vm/max_map_count
    
  • 永久调整参数

    sudo nano /etc/sysctl.d/99-custom.conf
    sudo sysctl -p
    

在这里插入图片描述

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值