--- old/src/java.base/linux/classes/jdk/internal/platform/CgroupInfo.java 2020-01-21 20:26:15.962260649 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/CgroupInfo.java 2020-01-21 20:26:15.827260346 +0100 @@ -37,7 +37,6 @@ private final String name; private final int hierarchyId; private final boolean enabled; - private String cgroupPath; private CgroupInfo(String name, int hierarchyId, boolean enabled) { this.name = name; @@ -57,14 +56,6 @@ return enabled; } - String getCgroupPath() { - return cgroupPath; - } - - void setCgroupPath(String cgroupPath) { - this.cgroupPath = cgroupPath; - } - static CgroupInfo fromCgroupsLine(String line) { String[] tokens = line.split("\\s+"); if (tokens.length != 4) { --- old/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java 2020-01-21 20:26:16.620262125 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/CgroupMetrics.java 2020-01-21 20:26:16.482261816 +0100 @@ -29,9 +29,9 @@ public class CgroupMetrics implements Metrics { - private final CgroupSubsystem subsystem; + protected final CgroupSubsystem subsystem; - private CgroupMetrics(CgroupSubsystem subsystem) { + CgroupMetrics(CgroupSubsystem subsystem) { this.subsystem = Objects.requireNonNull(subsystem); } @@ -115,17 +115,6 @@ return subsystem.getEffectiveCpuSetMems(); } - @Override - public double getCpuSetMemoryPressure() { - return subsystem.getCpuSetMemoryPressure(); - } - - @Override - public Boolean isCpuSetMemoryPressureEnabled() { - return subsystem.isCpuSetMemoryPressureEnabled(); - } - - @Override public long getMemoryFailCount() { return subsystem.getMemoryFailCount(); } @@ -136,81 +125,26 @@ } @Override - public long getMemoryMaxUsage() { - return subsystem.getMemoryMaxUsage(); - } - - @Override public long getMemoryUsage() { return subsystem.getMemoryUsage(); } @Override - public long getKernelMemoryFailCount() { - return subsystem.getKernelMemoryFailCount(); - } - - @Override - public long getKernelMemoryLimit() { - return subsystem.getKernelMemoryLimit(); - } - - @Override - public long getKernelMemoryMaxUsage() { - return subsystem.getKernelMemoryMaxUsage(); - } - - @Override - public long getKernelMemoryUsage() { - return subsystem.getKernelMemoryUsage(); - } - - @Override - public long getTcpMemoryFailCount() { - return subsystem.getTcpMemoryFailCount(); - } - - @Override - public long getTcpMemoryLimit() { - return subsystem.getTcpMemoryLimit(); - } - - @Override - public long getTcpMemoryMaxUsage() { - return subsystem.getTcpMemoryMaxUsage(); - } - - @Override public long getTcpMemoryUsage() { return subsystem.getTcpMemoryUsage(); } @Override - public long getMemoryAndSwapFailCount() { - return subsystem.getMemoryAndSwapFailCount(); - } - - @Override public long getMemoryAndSwapLimit() { return subsystem.getMemoryAndSwapLimit(); } @Override - public long getMemoryAndSwapMaxUsage() { - return subsystem.getMemoryAndSwapMaxUsage(); - } - - @Override public long getMemoryAndSwapUsage() { return subsystem.getMemoryAndSwapUsage(); } @Override - public Boolean isMemoryOOMKillEnabled() { - return subsystem.isMemoryOOMKillEnabled(); - } - - @Override public long getMemorySoftLimit() { return subsystem.getMemorySoftLimit(); } @@ -226,8 +160,7 @@ } public static Metrics getInstance() { - CgroupSubsystem subsystem = CgroupSubsystemFactory.create(); - return new CgroupMetrics(subsystem); + return CgroupSubsystemFactory.create(); } } \ No newline at end of file --- old/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java 2020-01-21 20:26:17.280263606 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystem.java 2020-01-21 20:26:17.144263301 +0100 @@ -30,4 +30,21 @@ * */ public interface CgroupSubsystem extends Metrics { + + /** + * Returned for metrics of type long if the underlying implementation + * has determined that no limit is being imposed. + */ + public static final long LONG_RETVAL_UNLIMITED = -1; + /** + * Returned for metrics of type long if the underlying implementation + * doesn't support that metric. + */ + public static final long LONG_RETVAL_NOT_SUPPORTED = -2; + public static final double DOUBLE_RETVAL_NOT_SUPPORTED = LONG_RETVAL_NOT_SUPPORTED; + /** + * Returned for metrics of type Boolean if the underlying implementation + * doesn't support that metric. + */ + public static final Boolean BOOL_RETVAL_NOT_SUPPORTED = null; } --- old/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java 2020-01-21 20:26:17.933265071 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemController.java 2020-01-21 20:26:17.797264766 +0100 @@ -48,12 +48,12 @@ /** * getStringValue * - * Return the first line of the file "parm" argument from the controller. + * Return the first line of the file "param" argument from the controller. * * TODO: Consider using weak references for caching BufferedReader object. * * @param controller - * @param parm + * @param param * @return Returns the contents of the file specified by param. */ public static String getStringValue(CgroupSubsystemController controller, String param) { @@ -72,7 +72,7 @@ String param, String match, Function conversion) { - long retval = Metrics.LONG_RETVAL_UNLIMITED; + long retval = CgroupSubsystem.LONG_RETVAL_UNLIMITED; try { Path filePath = Paths.get(controller.path(), param); List lines = CgroupUtil.readAllLinesPrivileged(filePath); @@ -109,19 +109,19 @@ * getSubSystemlongEntry * * Return the long value from the line containing the string "entryname" - * within file "parm" in the "subsystem". + * within file "param" in the "subsystem". * * TODO: Consider using weak references for caching BufferedReader object. * * @param controller - * @param parm + * @param param * @param entryname * @return long value */ - public static long getLongEntry(CgroupSubsystemController controller, String parm, String entryname) { + public static long getLongEntry(CgroupSubsystemController controller, String param, String entryname) { if (controller == null) return 0L; - try (Stream lines = CgroupUtil.readFilePrivileged(Paths.get(controller.path(), parm))) { + try (Stream lines = CgroupUtil.readFilePrivileged(Paths.get(controller.path(), param))) { Optional result = lines.map(line -> line.split(" ")) .filter(line -> (line.length == 2 && --- old/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java 2020-01-21 20:26:18.587266539 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/CgroupSubsystemFactory.java 2020-01-21 20:26:18.451266234 +0100 @@ -45,7 +45,7 @@ private static final String BLKIO_CTRL = "blkio"; private static final String MEMORY_CTRL = "memory"; - static CgroupSubsystem create() { + static CgroupMetrics create() { Map infos = new HashMap<>(); try { List lines = CgroupUtil.readAllLinesPrivileged(Paths.get("/proc/cgroups")); @@ -124,9 +124,9 @@ CgroupSubsystemController unified = new CgroupV2SubsystemController( mountPath, cgroupPath); - return new CgroupV2Subsystem(unified); + return new CgroupMetrics(new CgroupV2Subsystem(unified)); } else { - return CgroupV1Subsystem.getInstance(); + return new CgroupV1Metrics(CgroupV1Subsystem.getInstance()); } } } --- old/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java 2020-01-21 20:26:19.241268006 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1Subsystem.java 2020-01-21 20:26:19.103267696 +0100 @@ -33,9 +33,9 @@ import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; import jdk.internal.platform.CgroupUtil; -import jdk.internal.platform.Metrics; +import jdk.internal.platform.MetricsCgroupV1; -public class CgroupV1Subsystem implements CgroupSubsystem { +public class CgroupV1Subsystem implements CgroupSubsystem, MetricsCgroupV1 { private CgroupV1MemorySubSystemController memory; private CgroupV1SubsystemController cpu; private CgroupV1SubsystemController cpuacct; @@ -320,7 +320,7 @@ public long getCpuShares() { long retval = getLongValue(cpu, "cpu.shares"); if (retval == 0 || retval == 1024) - return Metrics.LONG_RETVAL_UNLIMITED; + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; else return retval; } --- old/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java 2020-01-21 20:26:19.899269482 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/CgroupV1SubsystemController.java 2020-01-21 20:26:19.764269180 +0100 @@ -25,8 +25,8 @@ package jdk.internal.platform.cgroupv1; +import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; -import jdk.internal.platform.Metrics; public class CgroupV1SubsystemController implements CgroupSubsystemController { @@ -77,6 +77,6 @@ } public static long longValOrUnlimited(long value) { - return value > UNLIMITED_MIN ? Metrics.LONG_RETVAL_UNLIMITED : value; + return value > UNLIMITED_MIN ? CgroupSubsystem.LONG_RETVAL_UNLIMITED : value; } } --- old/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java 2020-01-21 20:26:20.565270977 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2Subsystem.java 2020-01-21 20:26:20.420270651 +0100 @@ -34,7 +34,6 @@ import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; import jdk.internal.platform.CgroupUtil; -import jdk.internal.platform.Metrics; public class CgroupV2Subsystem implements CgroupSubsystem { @@ -96,12 +95,12 @@ String cpuMaxRaw = CgroupSubsystemController.getStringValue(unified, "cpu.max"); if (cpuMaxRaw == null) { // likely file not found - return Metrics.LONG_RETVAL_UNLIMITED; + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } // $MAX $PERIOD String[] tokens = cpuMaxRaw.split("\\s+"); if (tokens.length != 2) { - return Metrics.LONG_RETVAL_UNLIMITED; + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } String quota = tokens[tokenIdx]; return limitFromString(quota); @@ -109,7 +108,7 @@ private long limitFromString(String strVal) { if (MAX_VAL.equals(strVal)) { - return Metrics.LONG_RETVAL_UNLIMITED; + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } return Long.parseLong(strVal); } @@ -118,7 +117,7 @@ public long getCpuShares() { long sharesRaw = getLongVal("cpu.weight"); if (sharesRaw == 100 || sharesRaw == 0) { - return Metrics.LONG_RETVAL_UNLIMITED; + return CgroupSubsystem.LONG_RETVAL_UNLIMITED; } int shares = (int)sharesRaw; // CPU shares (OCI) value needs to get translated into @@ -193,16 +192,6 @@ } @Override - public double getCpuSetMemoryPressure() { - return Metrics.DOUBLE_RETVAL_NOT_SUPPORTED; - } - - @Override - public Boolean isCpuSetMemoryPressureEnabled() { - return Metrics.BOOL_RETVAL_NOT_SUPPORTED; - } - - @Override public long getMemoryFailCount() { return CgroupSubsystemController.getLongEntry(unified, "memory.events", "max"); } @@ -214,82 +203,27 @@ } @Override - public long getMemoryMaxUsage() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override public long getMemoryUsage() { return getLongVal("memory.current"); } @Override - public long getKernelMemoryFailCount() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override - public long getKernelMemoryLimit() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override - public long getKernelMemoryMaxUsage() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override - public long getKernelMemoryUsage() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override - public long getTcpMemoryFailCount() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override - public long getTcpMemoryLimit() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override - public long getTcpMemoryMaxUsage() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override public long getTcpMemoryUsage() { return CgroupSubsystemController.getLongEntry(unified, "memory.stat", "sock"); } @Override - public long getMemoryAndSwapFailCount() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override public long getMemoryAndSwapLimit() { String strVal = CgroupSubsystemController.getStringValue(unified, "memory.swap.max"); return limitFromString(strVal); } @Override - public long getMemoryAndSwapMaxUsage() { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; - } - - @Override public long getMemoryAndSwapUsage() { return getLongVal("memory.swap.current"); } @Override - public Boolean isMemoryOOMKillEnabled() { - return Metrics.BOOL_RETVAL_NOT_SUPPORTED; - } - - @Override public long getMemorySoftLimit() { String softLimitStr = CgroupSubsystemController.getStringValue(unified, "memory.high"); return limitFromString(softLimitStr); @@ -312,7 +246,7 @@ .map(mapFunc) .collect(Collectors.summingLong(e -> e)); } catch (IOException e) { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; + return CgroupSubsystem.LONG_RETVAL_NOT_SUPPORTED; } } --- old/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2SubsystemController.java 2020-01-21 20:26:21.222272451 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/cgroupv2/CgroupV2SubsystemController.java 2020-01-21 20:26:21.085272143 +0100 @@ -27,8 +27,8 @@ import java.nio.file.Paths; +import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.CgroupSubsystemController; -import jdk.internal.platform.Metrics; public class CgroupV2SubsystemController implements CgroupSubsystemController { @@ -44,6 +44,6 @@ } public static long convertStringToLong(String strval) { - return CgroupSubsystemController.convertStringToLong(strval, Metrics.LONG_RETVAL_UNLIMITED); + return CgroupSubsystemController.convertStringToLong(strval, CgroupSubsystem.LONG_RETVAL_UNLIMITED); } } --- old/src/java.base/share/classes/jdk/internal/platform/Metrics.java 2020-01-21 20:26:21.876273918 +0100 +++ new/src/java.base/share/classes/jdk/internal/platform/Metrics.java 2020-01-21 20:26:21.739273611 +0100 @@ -50,23 +50,6 @@ public interface Metrics { /** - * Returned for metrics of type long if the underlying implementation - * has determined that no limit is being imposed. - */ - public static final long LONG_RETVAL_UNLIMITED = -1; - /** - * Returned for metrics of type long if the underlying implementation - * doesn't support that metric. - */ - public static final long LONG_RETVAL_NOT_SUPPORTED = -2; - public static final double DOUBLE_RETVAL_NOT_SUPPORTED = LONG_RETVAL_NOT_SUPPORTED; - /** - * Returned for metrics of type Boolean if the underlying implementation - * doesn't support that metric. - */ - public static final Boolean BOOL_RETVAL_NOT_SUPPORTED = null; - - /** * Returns an instance of the Metrics class. * * @return Metrics object or null if not supported on this platform. @@ -288,28 +271,6 @@ */ public int[] getEffectiveCpuSetMems(); - /** - * Returns the (attempts per second * 1000), if enabled, that the - * operating system tries to satisfy a memory request for any - * process in the current Isolation Group when no free memory is - * readily available. Use {@link #isCpuSetMemoryPressureEnabled()} to - * determine if this support is enabled. - * - * @return Memory pressure or 0 if not enabled or -2 if metric is not - * available. - * - */ - public double getCpuSetMemoryPressure(); - - /** - * Returns the state of the memory pressure detection support. - * - * @return true if support is available and enabled. null if metric is - * not available. false otherwise. - * - */ - public Boolean isCpuSetMemoryPressureEnabled(); - /***************************************************************** * Memory Subsystem ****************************************************************/ @@ -335,16 +296,6 @@ public long getMemoryLimit(); /** - * Returns the largest amount of physical memory, in bytes, that - * have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or -2 if this - * metric is not available. - * - */ - public long getMemoryMaxUsage(); - - /** * Returns the amount of physical memory, in bytes, that is currently * allocated in the current Isolation Group. * @@ -355,76 +306,6 @@ public long getMemoryUsage(); /** - * Returns the number of times that kernel memory requests in the - * Isolation Group have exceeded the kernel memory limit. - * - * @return The number of exceeded requests or -2 if metric - * is not available. - * - */ - public long getKernelMemoryFailCount(); - - /** - * Returns the maximum amount of kernel physical memory, in bytes, that - * can be allocated in the Isolation Group. - * - * @return The maximum amount of memory in bytes or -1 if - * there is no limit set or -2 if this metric is not available. - * - */ - public long getKernelMemoryLimit(); - - /** - * Returns the largest amount of kernel physical memory, in bytes, that - * have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or -2 if this - * metric is not available. - * - */ - public long getKernelMemoryMaxUsage(); - - /** - * Returns the amount of kernel physical memory, in bytes, that - * is currently allocated in the current Isolation Group. - * - * @return The amount of memory in bytes allocated or -2 if this - * metric is not available. - * - */ - public long getKernelMemoryUsage(); - - /** - * Returns the number of times that networking memory requests in the - * Isolation Group have exceeded the kernel memory limit. - * - * @return The number of exceeded requests or -2 if the metric - * is not available. - * - */ - public long getTcpMemoryFailCount(); - - /** - * Returns the maximum amount of networking physical memory, in bytes, - * that can be allocated in the Isolation Group. - * - * @return The maximum amount of memory in bytes or -1 if - * there is no limit or -2 if this metric is not available. - * - */ - public long getTcpMemoryLimit(); - - /** - * Returns the largest amount of networking physical memory, in bytes, - * that have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or -2 if this - * metric is not available. - * - */ - public long getTcpMemoryMaxUsage(); - - /** * Returns the amount of networking physical memory, in bytes, that * is currently allocated in the current Isolation Group. * @@ -435,16 +316,6 @@ public long getTcpMemoryUsage(); /** - * Returns the number of times that user memory requests in the - * Isolation Group have exceeded the memory + swap limit. - * - * @return The number of exceeded requests or -2 if the metric - * is not available. - * - */ - public long getMemoryAndSwapFailCount(); - - /** * Returns the maximum amount of physical memory and swap space, * in bytes, that can be allocated in the Isolation Group. * @@ -455,16 +326,6 @@ public long getMemoryAndSwapLimit(); /** - * Returns the largest amount of physical memory and swap space, - * in bytes, that have been allocated in the Isolation Group. - * - * @return The largest amount of memory in bytes or -2 if this - * metric is not available. - * - */ - public long getMemoryAndSwapMaxUsage(); - - /** * Returns the amount of physical memory and swap space, in bytes, * that is currently allocated in the current Isolation Group. * @@ -475,18 +336,6 @@ public long getMemoryAndSwapUsage(); /** - * Returns the state of the Operating System Out of Memory termination - * policy. - * - * @return Returns true if operating system will terminate processes - * in the Isolation Group that exceed the amount of available - * memory, otherwise false. null will be returned if this - * capability is not available on the current operating system. - * - */ - public Boolean isMemoryOOMKillEnabled(); - - /** * Returns the hint to the operating system that allows groups * to specify the minimum amount of physical memory that they need to * achieve reasonable performance in low memory systems. This allows --- old/src/java.base/share/classes/sun/launcher/LauncherHelper.java 2020-01-21 20:26:22.534275395 +0100 +++ new/src/java.base/share/classes/sun/launcher/LauncherHelper.java 2020-01-21 20:26:22.396275085 +0100 @@ -87,6 +87,7 @@ import jdk.internal.module.Modules; import jdk.internal.platform.Container; import jdk.internal.platform.Metrics; +import jdk.internal.platform.MetricsCgroupV1; public final class LauncherHelper { @@ -119,6 +120,7 @@ private static final String defaultBundleName = "sun.launcher.resources.launcher"; + private static final long LONG_RETVAL_NOT_SUPPORTED = -2; private static class ResourceBundleHolder { private static final ResourceBundle RB = ResourceBundle.getBundle(defaultBundleName); @@ -393,9 +395,6 @@ ostream.println(INDENT + "List of Available Memory Nodes: N/A"); } - ostream.println(formatBoolean(c.isCpuSetMemoryPressureEnabled(), - INDENT + "CPUSet Memory Pressure Enabled: ")); - long limit = c.getMemoryLimit(); ostream.println(formatLimitString(limit, INDENT + "Memory Limit: ")); @@ -405,14 +404,18 @@ limit = c.getMemoryAndSwapLimit(); ostream.println(formatLimitString(limit, INDENT + "Memory & Swap Limit: ")); - limit = c.getKernelMemoryLimit(); - ostream.println(formatLimitString(limit, INDENT + "Kernel Memory Limit: ")); - - limit = c.getTcpMemoryLimit(); - ostream.println(formatLimitString(limit, INDENT + "TCP Memory Limit: ")); - - ostream.println(formatBoolean(c.isMemoryOOMKillEnabled(), - INDENT + "Out Of Memory Killer Enabled: ")); + // Extended cgroupv1 specific metrics + if (c instanceof MetricsCgroupV1) { + MetricsCgroupV1 cgroupV1 = (MetricsCgroupV1)c; + limit = cgroupV1.getKernelMemoryLimit(); + ostream.println(formatLimitString(limit, INDENT + "Kernel Memory Limit: ")); + limit = cgroupV1.getTcpMemoryLimit(); + ostream.println(formatLimitString(limit, INDENT + "TCP Memory Limit: ")); + Boolean value = cgroupV1.isMemoryOOMKillEnabled(); + ostream.println(formatBoolean(value, INDENT + "Out Of Memory Killer Enabled: ")); + value = cgroupV1.isCpuSetMemoryPressureEnabled(); + ostream.println(formatBoolean(value, INDENT + "CPUSet Memory Pressure Enabled: ")); + } ostream.println(""); } @@ -420,7 +423,7 @@ private static String formatLimitString(long limit, String prefix) { if (limit >= 0) { return prefix + SizePrefix.scaleValue(limit); - } else if (limit == Metrics.LONG_RETVAL_NOT_SUPPORTED) { + } else if (limit == LONG_RETVAL_NOT_SUPPORTED) { return prefix + "N/A"; } else { return prefix + "Unlimited"; @@ -430,7 +433,7 @@ private static String formatCpuVal(long cpuVal, String prefix) { if (cpuVal >= 0) { return prefix + cpuVal + "us"; - } else if (cpuVal == Metrics.LONG_RETVAL_NOT_SUPPORTED) { + } else if (cpuVal == LONG_RETVAL_NOT_SUPPORTED) { return prefix + "N/A"; } else { return prefix + cpuVal; @@ -438,10 +441,10 @@ } private static String formatBoolean(Boolean value, String prefix) { - if (value == Metrics.BOOL_RETVAL_NOT_SUPPORTED) { - return prefix + "N/A"; - } else { + if (value != null) { return prefix + value; + } else { + return prefix + "N/A"; } } --- old/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java 2020-01-21 20:26:23.196276880 +0100 +++ new/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java 2020-01-21 20:26:23.060276575 +0100 @@ -23,6 +23,7 @@ import java.util.Arrays; import jdk.internal.platform.Metrics; +import jdk.internal.platform.MetricsCgroupV1; public class MetricsMemoryTester { public static void main(String[] args) { @@ -107,14 +108,20 @@ } private static void testKernelMemoryLimit(String value) { - long limit = getMemoryValue(value); - long kmemlimit = Metrics.systemMetrics().getKernelMemoryLimit(); - if (kmemlimit != 0 && limit != kmemlimit) { - throw new RuntimeException("Kernel Memory limit not equal, expected : [" - + limit + "]" + ", got : [" - + kmemlimit + "]"); - } - System.out.println("TEST PASSED!!!"); + Metrics m = Metrics.systemMetrics(); + if (m instanceof MetricsCgroupV1) { + MetricsCgroupV1 mCgroupV1 = (MetricsCgroupV1)m; + System.out.println("TEST PASSED!!!"); + long limit = getMemoryValue(value); + long kmemlimit = mCgroupV1.getKernelMemoryLimit(); + if (kmemlimit != 0 && limit != kmemlimit) { + throw new RuntimeException("Kernel Memory limit not equal, expected : [" + + limit + "]" + ", got : [" + + kmemlimit + "]"); + } + } else { + throw new RuntimeException("oomKillFlag test not supported for cgroups v2"); + } } private static void testMemoryAndSwapLimit(String memory, String memAndSwap) { @@ -146,9 +153,17 @@ } private static void testOomKillFlag(boolean oomKillFlag) { - if (!(oomKillFlag ^ Metrics.systemMetrics().isMemoryOOMKillEnabled())) { - throw new RuntimeException("oomKillFlag error"); + Metrics m = Metrics.systemMetrics(); + if (m instanceof MetricsCgroupV1) { + MetricsCgroupV1 mCgroupV1 = (MetricsCgroupV1)m; + Boolean expected = Boolean.valueOf(oomKillFlag); + Boolean actual = mCgroupV1.isMemoryOOMKillEnabled(); + if (!(expected.equals(actual))) { + throw new RuntimeException("oomKillFlag error"); + } + System.out.println("TEST PASSED!!!"); + } else { + throw new RuntimeException("oomKillFlag test not supported for cgroups v2"); } - System.out.println("TEST PASSED!!!"); } } --- old/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java 2020-01-21 20:26:23.851278350 +0100 +++ new/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java 2020-01-21 20:26:23.713278040 +0100 @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; + import jdk.test.lib.Asserts; @@ -54,8 +55,7 @@ public static int getNumCpus() { String path = "/proc/cpuinfo"; - try { - Stream stream = Files.lines(Paths.get(path)); + try(Stream stream = Files.lines(Paths.get(path))) { return (int) stream.filter(line -> line.startsWith("processor")).count(); } catch (IOException e) { return 0; --- old/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV1.java 2020-01-21 20:26:24.509279826 +0100 +++ new/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV1.java 2020-01-21 20:26:24.372279519 +0100 @@ -39,6 +39,7 @@ import java.util.stream.Stream; import jdk.internal.platform.Metrics; +import jdk.internal.platform.MetricsCgroupV1; public class MetricsTesterCgroupV1 implements CgroupMetricsTester { @@ -203,7 +204,7 @@ } public void testMemorySubsystem() { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); // User Memory long oldVal = metrics.getMemoryFailCount(); @@ -327,7 +328,7 @@ } public void testCpuAccounting() { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); long oldVal = metrics.getCpuUsage(); long newVal = getLongValueFromFile(Controller.CPUACCT, "cpuacct.usage"); @@ -366,7 +367,7 @@ } public void testCpuSchedulingMetrics() { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); long oldVal = metrics.getCpuPeriod(); long newVal = getLongValueFromFile(Controller.CPUACCT, "cpu.cfs_period_us"); if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { @@ -406,7 +407,7 @@ } public void testCpuSets() { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); Integer[] oldVal = Arrays.stream(metrics.getCpuSetCpus()).boxed().toArray(Integer[]::new); Arrays.sort(oldVal); @@ -474,7 +475,7 @@ } private void testBlkIO() { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); long oldVal = metrics.getBlkIOServiceCount(); long newVal = getLongValueFromFile(Controller.BLKIO, "blkio.throttle.io_service_bytes", "Total"); @@ -491,7 +492,7 @@ } public void testCpuConsumption() throws IOException, InterruptedException { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); // make system call long newSysVal = metrics.getCpuSystemUsage(); long newUserVal = metrics.getCpuUserUsage(); @@ -530,7 +531,7 @@ } public void testMemoryUsage() throws Exception { - Metrics metrics = Metrics.systemMetrics(); + MetricsCgroupV1 metrics = (MetricsCgroupV1)Metrics.systemMetrics(); long memoryMaxUsage = metrics.getMemoryMaxUsage(); long memoryUsage = metrics.getMemoryUsage(); long newMemoryMaxUsage = 0, newMemoryUsage = 0; --- old/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java 2020-01-21 20:26:25.168281305 +0100 +++ new/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java 2020-01-21 20:26:25.032280999 +0100 @@ -34,13 +34,12 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import jdk.internal.platform.CgroupSubsystem; import jdk.internal.platform.Metrics; -import jdk.test.lib.Asserts; public class MetricsTesterCgroupV2 implements CgroupMetricsTester { private static final long UNLIMITED = -1; - private static final long NOT_SUPPORTED = -2; private static final UnifiedController UNIFIED = new UnifiedController(); private static final String MAX = "max"; private static final int PER_CPU_SHARES = 1024; @@ -153,21 +152,6 @@ CgroupMetricsTester.warn(UnifiedController.NAME, metric, oldVal, newVal); } - private void verifyNotSupported(long metricVal) { - Asserts.assertEquals(metricVal, NOT_SUPPORTED, "Expected metric to be not supported!"); - } - - private void verifyNotSupported(double metricVal) { - if (!CgroupMetricsTester.compareWithErrorMargin(NOT_SUPPORTED, metricVal)) { - throw new RuntimeException("Metric not supported, got: " + metricVal + - " expected: " + NOT_SUPPORTED); - } - } - - private void verifyPerCpuNotSupported(long[] perCpuUsage) { - Asserts.assertNull(perCpuUsage, "perCpuUsage expected to be not supported"); - } - private long getCpuShares(String file) { long rawVal = getLongValueFromFile(file); if (rawVal == 0 || rawVal == 100) { @@ -243,18 +227,6 @@ if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { fail("memory.current", oldVal, newVal); } - verifyNotSupported(metrics.getMemoryMaxUsage()); - - // Kernel memory - verifyNotSupported(metrics.getKernelMemoryFailCount()); - verifyNotSupported(metrics.getKernelMemoryLimit()); - verifyNotSupported(metrics.getKernelMemoryMaxUsage()); - verifyNotSupported(metrics.getKernelMemoryUsage()); - - //TCP Memory - verifyNotSupported(metrics.getTcpMemoryFailCount()); - verifyNotSupported(metrics.getTcpMemoryLimit()); - verifyNotSupported(metrics.getTcpMemoryMaxUsage()); oldVal = metrics.getTcpMemoryUsage(); newVal = getLongValueEntryFromFile("memory.stat", "sock"); @@ -262,10 +234,6 @@ fail("memory.stat[sock]", oldVal, newVal); } - // Memory and Swap - verifyNotSupported(metrics.getMemoryAndSwapFailCount()); - verifyNotSupported(metrics.getMemoryAndSwapMaxUsage()); - oldVal = metrics.getMemoryAndSwapLimit(); newVal = getLongLimitValueFromFile("memory.swap.max"); if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { @@ -284,7 +252,6 @@ fail("memory.high", oldVal, newVal); } - Asserts.assertNull(metrics.isMemoryOOMKillEnabled(), "Not supported"); } @Override @@ -297,8 +264,6 @@ warn("cpu.stat[usage_usec]", oldVal, newVal); } - verifyPerCpuNotSupported(metrics.getPerCpuUsage()); - oldVal = metrics.getCpuUserUsage(); newVal = TimeUnit.MICROSECONDS.toNanos(getLongValueEntryFromFile("cpu.stat", "user_usec")); if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { @@ -400,9 +365,6 @@ fail("cpuset.mems.effective", Arrays.toString(oldVal), Arrays.toString(newVal)); } - - verifyNotSupported(metrics.getCpuSetMemoryPressure()); - Asserts.assertNull(metrics.isCpuSetMemoryPressureEnabled(), "Should be not supported"); } private int[] mapNullToEmpty(int[] cpus) { @@ -422,8 +384,6 @@ long newUserVal = metrics.getCpuUserUsage(); long newUsage = metrics.getCpuUsage(); - verifyPerCpuNotSupported(metrics.getPerCpuUsage()); - // system/user CPU usage counters may be slowly increasing. // allow for equal values for a pass if (newSysVal < startSysVal) { @@ -444,9 +404,8 @@ @Override public void testMemoryUsage() { Metrics metrics = Metrics.systemMetrics(); - long memoryMaxUsage = metrics.getMemoryMaxUsage(); long memoryUsage = metrics.getMemoryUsage(); - long newMemoryMaxUsage = 0, newMemoryUsage = 0; + long newMemoryUsage = 0; // allocate memory in a loop and check more than once for new values // otherwise we might occasionally see the effect of decreasing new memory @@ -459,12 +418,6 @@ break; } } - newMemoryMaxUsage = metrics.getMemoryMaxUsage(); - - if (newMemoryMaxUsage < memoryMaxUsage) { - fail("getMemoryMaxUsage", memoryMaxUsage, - newMemoryMaxUsage); - } if (newMemoryUsage < memoryUsage) { fail("getMemoryUsage", memoryUsage, newMemoryUsage); @@ -511,7 +464,7 @@ return accumulator; }).collect(Collectors.summingLong(e -> e)); } catch (IOException e) { - return Metrics.LONG_RETVAL_NOT_SUPPORTED; + return CgroupSubsystem.LONG_RETVAL_NOT_SUPPORTED; } } } --- /dev/null 2020-01-21 14:53:15.299782962 +0100 +++ new/src/java.base/linux/classes/jdk/internal/platform/CgroupV1Metrics.java 2020-01-21 20:26:25.704282507 +0100 @@ -0,0 +1,78 @@ +package jdk.internal.platform; + +/** + * Cgroup v1 Metrics extensions + * + */ +public class CgroupV1Metrics extends CgroupMetrics implements MetricsCgroupV1 { + + CgroupV1Metrics(MetricsCgroupV1 subsystem) { + super((CgroupSubsystem)subsystem); + } + + @Override + public long getMemoryMaxUsage() { + return ((MetricsCgroupV1)subsystem).getMemoryMaxUsage(); + } + + @Override + public long getKernelMemoryFailCount() { + return ((MetricsCgroupV1)subsystem).getKernelMemoryFailCount(); + } + + @Override + public long getKernelMemoryLimit() { + return ((MetricsCgroupV1)subsystem).getKernelMemoryLimit(); + } + + @Override + public long getKernelMemoryMaxUsage() { + return ((MetricsCgroupV1)subsystem).getKernelMemoryMaxUsage(); + } + + @Override + public long getKernelMemoryUsage() { + return ((MetricsCgroupV1)subsystem).getKernelMemoryUsage(); + } + + @Override + public long getTcpMemoryFailCount() { + return ((MetricsCgroupV1)subsystem).getTcpMemoryFailCount(); + } + + @Override + public long getTcpMemoryLimit() { + return ((MetricsCgroupV1)subsystem).getTcpMemoryLimit(); + } + + @Override + public long getTcpMemoryMaxUsage() { + return ((MetricsCgroupV1)subsystem).getTcpMemoryMaxUsage(); + } + + @Override + public long getMemoryAndSwapFailCount() { + return ((MetricsCgroupV1)subsystem).getMemoryAndSwapFailCount(); + } + + @Override + public long getMemoryAndSwapMaxUsage() { + return ((MetricsCgroupV1)subsystem).getMemoryAndSwapMaxUsage(); + } + + @Override + public Boolean isMemoryOOMKillEnabled() { + return ((MetricsCgroupV1)subsystem).isMemoryOOMKillEnabled(); + } + + @Override + public double getCpuSetMemoryPressure() { + return ((MetricsCgroupV1)subsystem).getCpuSetMemoryPressure(); + } + + @Override + public Boolean isCpuSetMemoryPressureEnabled() { + return ((MetricsCgroupV1)subsystem).isCpuSetMemoryPressureEnabled(); + } + +} --- /dev/null 2020-01-21 14:53:15.299782962 +0100 +++ new/src/java.base/share/classes/jdk/internal/platform/MetricsCgroupV1.java 2020-01-21 20:26:26.368283997 +0100 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2020, Red Hat Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.platform; + +/** + * + * Cgroup v1 extensions to the Metrics interface. + * + */ +public interface MetricsCgroupV1 extends Metrics { + + /** + * Returns the largest amount of physical memory, in bytes, that + * have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -2 if this + * metric is not available. + * + */ + public long getMemoryMaxUsage(); + + /** + * Returns the number of times that kernel memory requests in the + * Isolation Group have exceeded the kernel memory limit. + * + * @return The number of exceeded requests or -2 if metric + * is not available. + * + */ + public long getKernelMemoryFailCount(); + + /** + * Returns the maximum amount of kernel physical memory, in bytes, that + * can be allocated in the Isolation Group. + * + * @return The maximum amount of memory in bytes or -1 if + * there is no limit set or -2 if this metric is not available. + * + */ + public long getKernelMemoryLimit(); + + /** + * Returns the largest amount of kernel physical memory, in bytes, that + * have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -2 if this + * metric is not available. + * + */ + public long getKernelMemoryMaxUsage(); + + /** + * Returns the amount of kernel physical memory, in bytes, that + * is currently allocated in the current Isolation Group. + * + * @return The amount of memory in bytes allocated or -2 if this + * metric is not available. + * + */ + public long getKernelMemoryUsage(); + + /** + * Returns the number of times that networking memory requests in the + * Isolation Group have exceeded the kernel memory limit. + * + * @return The number of exceeded requests or -2 if the metric + * is not available. + * + */ + public long getTcpMemoryFailCount(); + + /** + * Returns the maximum amount of networking physical memory, in bytes, + * that can be allocated in the Isolation Group. + * + * @return The maximum amount of memory in bytes or -1 if + * there is no limit or -2 if this metric is not available. + * + */ + public long getTcpMemoryLimit(); + + /** + * Returns the largest amount of networking physical memory, in bytes, + * that have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -2 if this + * metric is not available. + * + */ + public long getTcpMemoryMaxUsage(); + + /** + * Returns the number of times that user memory requests in the + * Isolation Group have exceeded the memory + swap limit. + * + * @return The number of exceeded requests or -2 if the metric + * is not available. + * + */ + public long getMemoryAndSwapFailCount(); + + /** + * Returns the largest amount of physical memory and swap space, + * in bytes, that have been allocated in the Isolation Group. + * + * @return The largest amount of memory in bytes or -2 if this + * metric is not available. + * + */ + public long getMemoryAndSwapMaxUsage(); + + /** + * Returns the state of the Operating System Out of Memory termination + * policy. + * + * @return Returns true if operating system will terminate processes + * in the Isolation Group that exceed the amount of available + * memory, otherwise false. null will be returned if this + * capability is not available on the current operating system. + * + */ + public Boolean isMemoryOOMKillEnabled(); + + /** + * Returns the (attempts per second * 1000), if enabled, that the + * operating system tries to satisfy a memory request for any + * process in the current Isolation Group when no free memory is + * readily available. Use {@link #isCpuSetMemoryPressureEnabled()} to + * determine if this support is enabled. + * + * @return Memory pressure or 0 if not enabled or -2 if metric is not + * available. + * + */ + public double getCpuSetMemoryPressure(); + + /** + * Returns the state of the memory pressure detection support. + * + * @return true if support is available and enabled. null if metric is + * not available. false otherwise. + * + */ + public Boolean isCpuSetMemoryPressureEnabled(); +}