热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在容器内运行JVM时内存的问题

本文内容来自redhat某个人的文章首先声明了一个事实,docker容器的-m,kubernets的-limits都可以用来限制内存。当进程使用的内存超过限制时,会收到内核发来的KILL信号。但是

本文内容来自redhat某个人的文章

首先声明了一个事实,docker容器的-m,kubernets的-limits都可以用来限制内存。当进程使用的内存超过限制时,会收到内核发来的KILL信号。但是JVM完全不知道自己运行在容器内。

那么就有了一个问题“JVM内存超过容器限制的内存会怎样”。

作者做了一个实验,实验流程如下。使用如下命令启动了一个jboss的wildfly服务器,内存限制是50m

docker run -it –name mywildfly -m=50m jboss/wildfly
docker state 显示的信息如下

但是在一会后,Wildfly容器执行被中断,然后打印出信息如下

*** JBossAS process (55) received KILL signal ***
执行 docker inspect mywildfly -f ‘{{json .State}}' 查看容器信息

注意到 OOMKilled=true

 

 然后作者又做了另外一个样例。使用springboot开接口生成字符串。(启动参数加上 -XX:+PrintFlagsFinal )

docker run -it --rm --name mycontainer150 -p 8080:8080 -m 150M rafabene/java-container:openjdk

然后发生一个神奇的现象,-m=150m,但是JVM最大内存却到了241.7MB,内存使用219.8MB。

俩个问题。

1.为什么最大内存是241.7MB

2.-m=150M,为什么允许Java内存到220MB?

根据JVM9的自动设置参数文档,最大堆内存表示物理内存的四分之一。因为JVM感知不到容器的存在,所以会使用宿主机的信息来计算,如下查看参数信息

docker logs mycontainer150|grep -i MaxHeapSize
uintx MaxHeapSize := 262144000 {product}

-m150m,为什么Java能开到220MB?根据Docker文档,-m150m表示限制物理内存150M和150M虚拟内存。所以,俩个加起来总共是300M。这就是Java没有收到Kill的原因。

回到刚开始的问题。“JVM内存超过容器限制的内存会怎样”。会被Kill掉,那么如何让JVM感知到容器内存的限制?

解决方案:

使用 fabric8/java-jboss-openjdk8-jdk 镜像(此镜像已经废弃,最新的是这个),意思是这个镜像会使用脚本计算容器的限制,并且只使用可用内存的百分之50。

  注意:是百分之50,刚好是物理内存的限制,这样JVM是最优的,没有内存页被交换到磁盘。

Dockerfile如下

FROM fabric8/java-jboss-openjdk8-jdk:1.4.0

ENV JAVA_APP_JAR java-container.jar
ENV AB_OFF true

EXPOSE 8080

ADD target/$JAVA_APP_JAR /deployments/

 

下面是Java9的解决方案。

如果你使用Java9,你可以显示设置JVM参数,-XX:+UnlockExperimentalVMOptions ,-XX:+UseCGroupMemoryLimitForHeap  来让JVM自动配置读取到CGgroups的真实内存值。

  注意:此时还是使用物理内存值的四分之一。

$ docker run -d --name mycontainer8g-jdk9 -p 8080:8080 -m 600M rafabene/java-container:openjdk-cgroup

$ docker logs mycontainer8g-jdk9|grep MaxHeapSize
size_t MaxHeapSize = 157286400 {product} {ergonomic}

 

下面是Java10的解决方案。

如果你使用Java10自动解决了这个,能自动感知到运行在容器内。那么-XX:+UnlockExperimentalVMOptions ,-XX:+UseCGroupMemoryLimitForHeap 这俩个参数就可以不要了。

如果加上这个参数,会看到如下警告

Option UseCGroupMemoryLimitForHeap was deprecated in version 10.0 and will likely be removed in a future release.
$ docker run -it --name mycontainer -p 8080:8080 -m 600M rafabene/java-container:openjdk10

 

                原文链接

 


推荐阅读
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
author-avatar
手机用户2502885711
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有