Path: blob/master/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java
40943 views
/*1* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/222324/*25* @test26* @key cgroups27* @summary Test JVM's memory resource awareness when running inside docker container28* @requires docker.support29* @library /test/lib30* @modules java.base/jdk.internal.misc31* java.base/jdk.internal.platform32* java.management33* jdk.jartool/sun.tools.jar34* @build AttemptOOM sun.hotspot.WhiteBox PrintContainerInfo CheckOperatingSystemMXBean35* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox36* @run driver TestMemoryAwareness37*/38import jdk.test.lib.containers.docker.Common;39import jdk.test.lib.containers.docker.DockerRunOptions;40import jdk.test.lib.containers.docker.DockerTestUtils;41import jdk.test.lib.process.OutputAnalyzer;4243public class TestMemoryAwareness {44private static final String imageName = Common.imageName("memory");4546public static void main(String[] args) throws Exception {47if (!DockerTestUtils.canTestDocker()) {48return;49}5051Common.prepareWhiteBox();52DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");5354try {55testMemoryLimit("100m", "104857600");56testMemoryLimit("500m", "524288000");57testMemoryLimit("1g", "1073741824");58testMemoryLimit("4g", "4294967296");5960testMemorySoftLimit("500m", "524288000");61testMemorySoftLimit("1g", "1073741824");6263// Add extra 10 Mb to allocator limit, to be sure to cause OOM64testOOM("256m", 256 + 10);6566testOperatingSystemMXBeanAwareness(67"100M", Integer.toString(((int) Math.pow(2, 20)) * 100),68"150M", Integer.toString(((int) Math.pow(2, 20)) * (150 - 100))69);70testOperatingSystemMXBeanAwareness(71"128M", Integer.toString(((int) Math.pow(2, 20)) * 128),72"256M", Integer.toString(((int) Math.pow(2, 20)) * (256 - 128))73);74testOperatingSystemMXBeanAwareness(75"1G", Integer.toString(((int) Math.pow(2, 20)) * 1024),76"1500M", Integer.toString(((int) Math.pow(2, 20)) * (1500 - 1024))77);78} finally {79if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {80DockerTestUtils.removeDockerImage(imageName);81}82}83}848586private static void testMemoryLimit(String valueToSet, String expectedTraceValue)87throws Exception {8889Common.logNewTestCase("memory limit: " + valueToSet);9091DockerRunOptions opts = Common.newOpts(imageName)92.addDockerOpts("--memory", valueToSet);9394Common.run(opts)95.shouldMatch("Memory Limit is:.*" + expectedTraceValue);96}979899private static void testMemorySoftLimit(String valueToSet, String expectedTraceValue)100throws Exception {101Common.logNewTestCase("memory soft limit: " + valueToSet);102103DockerRunOptions opts = Common.newOpts(imageName, "PrintContainerInfo");104Common.addWhiteBoxOpts(opts);105opts.addDockerOpts("--memory-reservation=" + valueToSet);106107Common.run(opts)108.shouldMatch("Memory Soft Limit.*" + expectedTraceValue);109}110111112// provoke OOM inside the container, see how VM reacts113private static void testOOM(String dockerMemLimit, int sizeToAllocInMb) throws Exception {114Common.logNewTestCase("OOM");115116// add "--memory-swappiness 0" so as to disable anonymous page swapping.117DockerRunOptions opts = Common.newOpts(imageName, "AttemptOOM")118.addDockerOpts("--memory", dockerMemLimit, "--memory-swappiness", "0", "--memory-swap", dockerMemLimit);119opts.classParams.add("" + sizeToAllocInMb);120121// make sure we avoid inherited Xmx settings from the jtreg vmoptions122// set Xmx ourselves instead123System.out.println("sizeToAllocInMb is:" + sizeToAllocInMb + " sizeToAllocInMb/2 is:" + sizeToAllocInMb/2);124String javaHeapSize = sizeToAllocInMb/2 + "m";125opts.addJavaOptsAppended("-Xmx" + javaHeapSize);126127OutputAnalyzer out = DockerTestUtils.dockerRunJava(opts);128129if (out.getExitValue() == 0) {130throw new RuntimeException("We exited successfully, but we wanted to provoke an OOM inside the container");131}132133out.shouldContain("Entering AttemptOOM main")134.shouldNotContain("AttemptOOM allocation successful")135.shouldContain("java.lang.OutOfMemoryError");136}137138private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, String expectedMemory,139String swapAllocation, String expectedSwap) throws Exception {140Common.logNewTestCase("Check OperatingSystemMXBean");141142DockerRunOptions opts = Common.newOpts(imageName, "CheckOperatingSystemMXBean")143.addDockerOpts(144"--memory", memoryAllocation,145"--memory-swap", swapAllocation146)147// CheckOperatingSystemMXBean uses Metrics (jdk.internal.platform) for148// diagnostics149.addJavaOpts("--add-exports")150.addJavaOpts("java.base/jdk.internal.platform=ALL-UNNAMED");151152OutputAnalyzer out = DockerTestUtils.dockerRunJava(opts);153out.shouldHaveExitValue(0)154.shouldContain("Checking OperatingSystemMXBean")155.shouldContain("OperatingSystemMXBean.getTotalPhysicalMemorySize: " + expectedMemory)156.shouldContain("OperatingSystemMXBean.getTotalMemorySize: " + expectedMemory)157.shouldMatch("OperatingSystemMXBean\\.getFreeMemorySize: [1-9][0-9]+")158.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+");159160// in case of warnings like : "Your kernel does not support swap limit capabilities161// or the cgroup is not mounted. Memory limited without swap."162// the getTotalSwapSpaceSize and getFreeSwapSpaceSize return the system163// values as the container setup isn't supported in that case.164try {165out.shouldContain("OperatingSystemMXBean.getTotalSwapSpaceSize: " + expectedSwap);166} catch(RuntimeException ex) {167out.shouldMatch("OperatingSystemMXBean.getTotalSwapSpaceSize: [0-9]+");168}169170try {171out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+");172} catch(RuntimeException ex) {173out.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: 0");174}175}176177}178179180