【问题标题】:JVM cant map reserved memory when running in Docker container在 Docker 容器中运行时,JVM 无法映射保留的内存
【发布时间】:2014-12-03 02:25:53
【问题描述】:

我似乎根本无法在我的服务器上的 Docker 容器中运行 java。即使发出java -version,我也会收到以下错误。

root@86088d679103:/# java -version
OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000035ce1000000, 2555904, 1) failed; error='Operation not permitted' (errno=1)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 2555904 bytes for committing reserved memory.
# An error report file with more information is saved as:
# //hs_err_pid17.log

据此,java不能为保留内存映射2.5Mb的空间?这似乎不对...

我在最后包含了完整的日志,但是为了提供一些额外的信息,我的系统报告了以下内容:

root@86088d679103:/# uname -m
x86_64
root@86088d679103:/# free -mh
             total       used       free     shared    buffers     cached
Mem:           15G       9.7G       5.8G       912K       148M       8.9G
-/+ buffers/cache:       639M        14G
Swap:          15G         0B        15G

谁能指出我正确的方向?

完整日志:https://gist.github.com/KayoticSully/e206c44681ce261674ba

更新

@Yobert 解决了这个问题,我强烈建议您通读 cmets 和聊天记录。里面有很好的信息。

对于那些想要使 Java 工作的最终命令的人:setfattr -n user.pax.flags -v "mr" /usr/bin/java

如果你的发行版默认没有安装setfattr,它应该通过paceman、apt-get等包含在可安装包attr中。

【问题讨论】:

    标签: java jvm docker mmap


    【解决方案1】:

    我在使用启用 Grsec 的内核时遇到了同样的问题。为了让 java 发挥出色,我不得不在 java 二进制文件上禁用 MPROTECT。您可以为此使用paxctl 实用程序:

    paxctl -m /usr/lib/jvm/java-7-openjdk/jre/bin/java
    

    如果您之前从未在该二进制文件上使用过paxctl -c,则需要先对该二进制文件执行此操作:

    paxctl -c /usr/lib/jvm/java-7-openjdk/jre/bin/java
    

    有关 paxctl 的更多信息,请访问:http://en.wikibooks.org/wiki/Grsecurity/Additional_Utilities

    【讨论】:

    • 这真是太棒了,但它对我不起作用......我确保在执行的实际 java 二进制文件中禁用了该标志,但同样的问题仍然存在。
    • 查看 dmesg——如果是 PAX 问题,当您尝试运行它时应该会看到一些内容。如果您的内核支持,还有一种通过 xattrs 而不是二进制标头设置安全属性的更新方法。也许您禁用了旧模式?
    • 嗯,我会尝试删除更多的标志,而不仅仅是 m。我们删除了 java 的 pemrs(虽然我不认为这是惯用的)
    • 好的,所以...我在 dmesg 中得到它,看起来像。 [24753.007799] grsec: From 10.0.0.106: denied RWX mmap of <anonymous mapping> by /usr/lib/jvm/java-8-jre/jre/bin/java[java:19815] uid/euid:1000/1000 gid/egid:1000/1000, parent /usr/bin/bash[bash:14286] uid/euid:1000/1000 gid/egid:1000/1000 我也需要在 Bash 上这样做吗?这是在我禁用 java 上的所有标志之后
    • Java bin 应该是您所需要的。也许它正在使用的 docker 容器中有不同的二进制文件?
    【解决方案2】:

    我在 Alpine Linux 上运行 Docker 时遇到了同样的问题,在启用 PaX 软模式后它可以工作:

    sysctl -w kernel.pax.softmode=1
    

    软模式默认会禁用大部分 PaX 功能,因此不建议启用它。正确的方法是使用 paxctl,如上所述。

    也可以看看这里: https://en.wikibooks.org/wiki/Grsecurity/Appendix/Grsecurity_and_PaX_Configuration_Options#Support_soft_mode

    【讨论】:

    • 这对我不起作用。我得到:[91msysctl: error: 'kernel.pax.softmode' is an unknown key 这是否意味着我的系统没有使用 PaX?​​span>
    • 谢谢。这在 3.7.0 标准版和虚拟版上确实对我有用。
    【解决方案3】:

    这也发生在我身上, 我们减少了 VM 上的 RAM 大小,几天后开始出现此错误,并且服务一直没有出现。

    解决方案 :: 我们减少了遇到此问题的应用程序或服务的堆大小,服务又恢复正常了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-02
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-04
      相关资源
      最近更新 更多