如果要将我们的应用程序移植到容器平台,如何在容器环境中配置Java堆内存大小呢?有没有最佳做法?在本文中,我们将讨论可用于指定Java堆内存大小的JVM参数以及最优选择。...在我们的容器环境中,通常可借助以下3个不同的选项来指定容器中的Java堆内存的大小。...仅当我们配置这两个JVM参数时,JVM才会从容器的内存大小中得出堆内存大小值,否则,它将从基础主机的内存大小中得出堆大小值。...除此之外,如果我们没有分配的容器的内存大小,那么JVM甚至不会启动(这比在进行事务处理时遇到OutOfMemoryError更好)。...在我看来,我倾向于使用-Xmx选项而不是-XX:MaxRAMFraction、-XX:MaxRAMPercentage选项来指定容器世界中的Java堆大小,原因如下:内存大小是决定应用程序性能的关键。
,比如:当你在物理机或者虚拟机上配置 JVM 参数时,你可以选择使用-Xmx/-Xms 来指定 Java 堆大小,但这样指定的话,就固定了 JVM 堆占用大小,如果将 Java 应用程序移植到容器或者说...在 K8S Pod 中,我们是否有必要指定 Java 堆大小配置 K8s 编排文件中有两个比较重要的资源限制参数 request / limit, 如下所示通过这两个参数我们可以限制内部容器占用的 CPU...具体可以参考文档[1] 当然你也可以通过如下命令进行简单的验证 JVM 是否能够感知容器内存的限制以及默认情况下占用内存的大小。...只有当您传递这两个 JVM 参数时,JVM 才会从容器的内存大小派生堆大小值,否则,它将从底层主机的内存大小派生堆大小值。...实践总结 你可以根据场景选择使用配置项(即 -XX:MaxRAMFraction、-XX:MaxRAMPercentage、-Xmx),但是请始终确保为容器分配的内存至少比您的容器多 25% 堆大小值
短短几年,容器就改变了软件行业的开发模式。也许,很多开发者已经开始在容器中运行 Java 应用。但是,对于容器化的 Java 应用程序,当遇到 CPU 和内存占用等问题时,还是有很多问题需要注意。...堆空间 如果说在容器中运行 Java 应用有一条核心定律,那么就是:对于在容器中运行的 Java 进程,不要手工设置 JVM 堆内存。相反的,设置容器的限制。 为什么?...如果不设置容器限制,同时运行在容器中的 Java 进程也没有显式设置 JVM 内存参数,那么 JVM 将会自动设置最大堆内存为运行节点总内存的 25%。...-XX:MaxRAMPercentage -XX:InitialRAMPercentage 本文不会详细介绍这些参数如何工作,但是关键点是这些参数可以在不需要直接设置堆内存大小的情况下用于调优 JVM...我们可以通过这些参数来修改初始、最小、最大堆内存。例如,设置 -XX:MaxRAMPercentage=50 将会允许 JVM 将容器内存的 50% 作为堆内存使用,而不是默认的 25%。
-XX:MaxRAMPercentage=80.0 需要注意的是,这MaxRAMPercentage并不限制 Java 进程可以使用的总内存大小。...➊提交的 JVM Heap 一旦达到heap限制就停止增加❷ ❸当提交的内存达到限制时,WSS/RSS 的系统内存停止heap增加。...这也解释了为什么在 pod 被OOMKilled之前没有发生 OutOfMemory 异常,因为堆内存和非堆内存都没有达到 JVM 的限制。...由于 G1 尽力完全避免 Full GC,并且仅根据 Java 堆占用和分配活动触发并发周期,因此它不会返回 Java 堆在许多情况下,除非从外部强制这样做,否则都会有内存。...这种行为在资源按使用付费的容器环境中尤其不利。即使在 VM 由于不活动而仅使用其分配的内存资源的一小部分的阶段,G1 也将保留所有 Java 堆。
特别是在容器环境下,不合理的JVM堆参数设置会导致各种异常现象产生,例如应用堆大小还未到达设置阈值或规格限制,就因为OOM导致重启等。...通过MaxRAMPercentage限制堆大小(推荐) 在容器环境下,Java只能获取服务器的配置,无法感知容器内存限制。...可以通过设置-Xmx来限制JVM堆大小,但该方式存在以下问题: 当规格大小调整后,需要重新设置堆大小参数。 当参数设置不合理时,会出现应用堆大小未达到阈值但容器OOM被强制关闭的情况。...当容器使用内存超过限制时,会出现容器OOM,导致容器被强制关闭。此时业务应用内存可能并未达到JVM堆大小上限,所以不会产生Dump日志。...因为系统自身组件存在内存开销,例如使用SLS进行日志收集时会占用一小部分的内存空间,所以不能将JVM堆大小设置为和规格内存大小相同的数值,需要为这些系统组件预留足够的内存空间。
但是,本篇仅限于对于这些内存的用途,使用限制,相关参数的分析,有些地方可能比较深入,有些地方可能需要结合本身用这块内存涉及的 JVM 模块去说,会放在另一系列文章详细描述。...Tracking 中申请的内存分为 reserved 和 committed JVM 内存申请与使用流程(全网最硬核 JVM 内存解析 - 2.JVM 内存申请与使用流程开始) Linux 下内存管理模型简述...通用初始化与扩展流程 目前最新的 JVM,主要根据三个指标初始化堆以及扩展或缩小堆: 最大堆大小 最小堆大小 初始堆大小 不同的 GC 情况下,初始化以及扩展的流程可能在某些细节不太一样,但是,大体的思路都是...由此引入第一个 JVM 参数,MaxRAM,这个参数是用来明确指定 JVM 进程可用内存大小的,如果没有指定,JVM 会自己读取系统可用内存。这个可用内存用来指导 JVM 限制最大堆内存。...,这个参数是在可用内存比较小的时候生效,即最大堆内存占用为可用内存的这个参数指定的百分比,默认为 50,即 50% MaxRAMPercentage:注意不要被名字迷惑,这个参数是在可用内存比较大的时候生效
出现此错误,一般都是如下两个原因导致: 内存中没有空间容纳新线程。 线程数超过操作系统限制。 出现无法创建native thread场景复现 搜索下日志,会发现海量日志系统中存在此类异常。...为机器分配更多的内存。 线程不是在 JVM 堆中创建的。它们是在 JVM 堆之外创建的。...:6 GB 堆大小(即 –Xms 和 –Xmx):5 GB Perm Gen 大小(即 -XX:MaxPermSize 和 -XX:MaxPermSize):512 MB 根据此配置,JVM 堆使用 5.5...为了缓解这个问题,您可以考虑将堆大小从 5GB 减少到 4GB(如果您的应用程序可以容纳它而不会遇到其他内存瓶颈);另外一种方式就是使用 java 系统属性 –Xss 来设置线程的内存大小。...另外如果使用k8s进行部署,一般会在编排文件层面限制容器内存或CPU大小,所以尽量不要使用 xms,xmx 参数,而要使用JVM内存参数新增了MaxRAMPercentage、InitialRAMPercentage
对于 Java 程序,JVM 设置是一个重要的环节。这里总结下我们项目里的最佳实践。 Java Heap 基础知识 默认情况下,JVM 自动分配的 heap 大小取决于机器配置。...为了解决这个问题,Java 10 引入了 +UseContainerSupport(默认情况下启用),通过这个特性,可以使得 JVM 在容器环境分配合理的堆内存。...这样当容器超过内存限制时,会抛出OOM异常,而不是杀死容器。 该特性在 Java 8u191+,10 及更高版本上可用。...注意:在191版本后,-XX:{Min|Max}RAMFraction 被弃用,引入了-XX:MaxRAMPercentage,其值介于 0.0 到 100.0 之间,默认值为 25.0。...,设置 -XX:+UseContainerSupport,设置 -XX:MaxRAMPercentage=75.0,这样为其他进程(debug、监控)留下足够的内存空间,又不会太浪费 RAM。
当我们将 JVM 生态中的关键要素,例如,垃圾收集器、堆大小和运行时编译器设置默认值时,许多技术人员(开发、运维人员)或许应该意识到在 Linux 容器生态中(诸如,Docker、Rkt、RunC...在本示例中,在 16 GB 的系统上分配了 4 GB 堆内存大小。除此之外,打印结果中的关键字 “MaxRAMFraction” 默认是 4,即意味着,每个 JVM 最多使用 25% 的机器物理内存。...+ 非堆内存的使用总和超出了 CGroup 的限制就会被操作系统 Kill 掉。...如果没有设置堆内存的大小,默认情况下,JVM 的 Max Heap Size 是操作系统的 1/4,我们知道 Docker 是通过 CGroups 来实现内存的限制,而 /proc 目录只是以只读的形式挂载到容器中...,默认情况下 Java 是看不到 CGroups 限制的内存大小,而是通过 /proc/meminfo 中的信息作为内存信息启动,这种不兼容的情况就会导致,容器分配的内存小于JVM Max Heap Size
Java Heap基础知识 默认情况下,jvm自动分配的heap大小取决于机器配置,比如我们到一台64G内存服务器: java -XX:+PrintFlagsFinal -version | grep...为了解决这个问题,Java 10 引入了 +UseContainerSupport(默认情况下启用),通过这个特性,可以使得JVM在容器环境分配合理的堆内存。...这样当容器超过内存限制时,会抛出OOM异常,而不是杀死容器。 该特性在Java 8u191 +,10及更高版本上可用。...注意,在191版本后,-XX:{Min|Max}RAMFraction 被弃用,引入了-XX:MaxRAMPercentage,其值介于0.0到100.0之间,默认值为25.0。...,设置 -XX:+UseContainerSupport,设置-XX:MaxRAMPercentage=75.0,这样为其他进程(debug、监控)留下足够的内存空间,又不会太浪费RAM。
但是,在容器中运行时,CPU和内存限制条件存储在`/proc/cgroups/...`中。...需要注意的是,这里`MinRAMPercentage`并不是用来设置堆大小的最小值,而是仅当物理服务器(或容器)中的总可用内存小于250MB时,JVM将用此参数来限制堆的大小。...同理,`MaxRAMPercentage`是当物理服务器(或容器)中的总可用内存大小超过250MB时,JVM将用此参数来限制堆的大小。 这几个参数已经向下移植到JDK 8u191。...需要注意的是,在指定`-Xms -Xmx`时,`InitialRAMPercentage`和`MaxRAMPercentage`将会失效。 关闭优化编译器 默认情况下,JVM有多个阶段的JIT编译。...如果您的应用处理100个并发请求,则它可能至少有100个线程,这相当于使用了100MB的线程栈空间。该内存不计入堆大小。我们可以使用以下参数来减小线程栈大小。
-Xmx 定义您分配给应用程序的最大堆大小。您可以像这样定义应用程序的堆大小: -Xmx2g 这带来了一个问题,我的应用程序的正确堆大小是多少?我应该为我的应用程序分配大堆大小还是小堆大小?...默认情况下,可用于存储此元数据信息的内存量是无限的(即受容器或机器的 RAM 大小限制)。您需要使用 -XX:MaxMetaspaceSize 参数来指定可用于存储元数据信息的内存量的上限。...现在让我们看一下有问题 JVM 的堆使用图: 您可以注意到图表的右端,即使 GC 反复运行,内存利用率也没有下降。这是应用程序遇到某种内存问题的典型迹象。...在“-XX:HeapDumpPath”中,您需要指定应该存储堆转储的文件路径。...如果它们的消耗超过一定的限制,则抛出 StackOverflowError。但您可以通过传递 -Xss 参数来增加线程的堆栈大小限制。
-Xmx定义要分配给应用程序的最大堆大小。。您可以这样定义应用程序的堆大小:-Xmx2g。 堆大小在影响应用性能和所需物理硬件需求。这带来了一个问题,我的应用程序正确的堆大小是多少?...默认情况下,可用于存储此元数据信息的内存量是无限的(即受您的容器或计算机的RAM大小的限制)。您需要使用-XX:MaxMetaspaceSize参数来指定可用于存储元数据信息的内存量的上限。...现在,让我们看一下有问题的JVM的堆使用情况图: ? 您可以注意到,在图表的右端,即使GC反复运行,内存利用率也没有下降。这是一个典型的内存泄漏迹象,表明该应用程序正在存在某种内存问题。...在-XX:HeapDumpPath中,需要指定堆转储所在的文件路径。...如果它们的使用量超出某个限制,则会引发StackOverflowError。可以通过传递-Xss参数来增加线程的堆栈大小限制。
Memory Management 在整体应用架构中,非生产环境情况下,一般 1GB 或者 2GB 的 RAM 就足够了。...未限制的内存用量 关于内存使用量如下图 JProfiler 制作的图表。如图所示,内存使用受堆影响,与非堆相比,它占用了大量空间。...Heap Non-Heap 当然,第一个明显的问题是我们是否需要在堆上运行我们的微服务应用程序的空间。答案是否定的,我们没有。现在,我们来简要介绍一下在 Java 8 中如何进行内存管理过程。...为了更好地了解下图,在运行 java -jar 命令时,可以使用以下参数设置 Java Heap 的内存限制: -Xms – JVM启动时的初始堆大小 -Xmx – 最大堆大小 -Xmn - 年轻代的大小...Metaspace : 它替代了 PermGem(Java 7中是JVM堆的一部分)。在 Metaspace 中,通过应用程序加载所有类和方法。
我们知道在Java虚拟机内存中,除了程序计数器外,其它的内存区域都可能会发生OutOfMemoryError异常。...在Java虚拟机中可以用-Xms参数和-Xmx参数设置Java堆的容量大小。...下面我们通过两个例子来演示上述的异常情况。 ? 由此可见,在单线程的情况下,无论栈的大小是多少,当内存无法分配时,虚拟机都会抛出StackOverflowError异常。...这是因为在其它文章中我们已经介绍过了,线程都有自己的独立内存空间,并且每个线程的内存空间大小是有限制的,如果创建的线程空间大小超过了系统内存时,如果继续创建线程,虚拟机无法为栈分配空间了,所以就会抛出OutOfMemoryError...方法区和运行时常量池 我们可以用下面的参数来设置方法区的大小 -XX:PermSize // 方法区设置的最小值 -XX:MaxPermSize // 方法区设置的最大值 本机直接内存溢出 我们可以用下面参数指定本机容量
使用企业性能包的客户将在运行于接近内存或CPU容量的JDK 8工作负载上立即看到好处。在Oracle自己的产品和云服务上进行的测试显示,高负载应用程序的内存和性能都提高了约40%。...即使JDK 8应用程序没有在接近容量的情况下运行,也可以看到高达5%的性能改进。 虽然企业性能包中包含的许多改进可以通过默认选项获得,但我们建议研究文档以最大化性能并最小化内存使用。...另外,在预料之中的是,其他在Java 8之后出现的实验性收集器(ZGC和Shenandoah)在生产系统中的使用量仍然很小,毕竟这两个收集器直到最近才达到生产就绪状态。...容器中的内存设置:比较内存设置时也会出现类似的趋势,在容器中往往倾向于更小的实例。...容器内和容器外运行的内存设置堆大小的百分比 报告数据显示,只有大约80%的容器化应用程序通过-Xmx或-XX:MaxRAMPercentage标记明确要求JVM内存上限。
)空余堆内存小于 40% 时,JVM 就会增大堆直到 -Xmx 的最大限制。...-Xmx:表示最大 Java 堆大小,当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃,因此一般建议堆的最大值设置为可用内存的最大值的80%。...1/4,默认(MinHeapFreeRatio参数可以调整)空余堆内存大于 70% 时,JVM 会减少堆直到-Xms 的最小限制。...-XX:MaxNewSize:设置最大新生代新生代内存大小 -XX:PermSize:设置持久代内存大小 -XX:MaxPermSize:设置最大值持久代内存大小,永久代不属于堆内存,堆内存只包含新生代和老年代...整个堆大小 = 新生代大小 + 老生代大小 + 永久代大小。在保证堆大小不变的情况下,增大新生代后,将会减小老生代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的 3/8。
在容器中运行应用程序时限制其对内存和CPU的使用绝对是一个好主意,它可以防止应用程序占用全部可用的内存和/或CPU,因而导致在同一系统上运行的其他容器无法响应。...限制资源的使用可以提高应用程序的可靠性和稳定性。它还为硬件容量的规划提供了依据。在像诸如Kubernetes或DC/OS这样的编排系统上运行容器时,这一点尤为重要。...在默认情况下,JVM会将max heap size(最大堆大小)设置为系统内存的1/4,并将一些线程池个数(比如说垃圾回收(GC))设置为与物理CPU内核的数量一致。我们一起来看看下面的例子。...此外,还有一些新设置: -XX:InitialRAMPercentage -XX:MaxRAMPercentage -XX:MinRAMPercentage 这些设置允许微调 heap size(堆大小...如果出于某种原因不需要新JVM的特性,可以使用-xx:-useContainerSupport关闭它。 三、结论 为基于JVM的应用程序设置正确的heap size(堆大小)是非常重要的。
领取专属 10元无门槛券
手把手带您无忧上云