8226575: OperatingSystemMXBean should be made container aware

Reviewed-by: dholmes, bobv, mchung, sspitsyn
This commit is contained in:
Daniil Titov 2019-12-11 19:20:57 -08:00
parent efdf413a20
commit 7b82266a15
16 changed files with 440 additions and 60 deletions

View File

@ -29,6 +29,9 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.stream.Stream;
import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem;
@ -70,7 +73,7 @@ public class Metrics implements jdk.internal.platform.Metrics {
* 34 28 0:29 / /sys/fs/cgroup/MemorySubSystem rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,MemorySubSystem
*/
try (Stream<String> lines =
Files.lines(Paths.get("/proc/self/mountinfo"))) {
readFilePrivileged(Paths.get("/proc/self/mountinfo"))) {
lines.filter(line -> line.contains(" - cgroup "))
.map(line -> line.split(" "))
@ -104,7 +107,7 @@ public class Metrics implements jdk.internal.platform.Metrics {
*
*/
try (Stream<String> lines =
Files.lines(Paths.get("/proc/self/cgroup"))) {
readFilePrivileged(Paths.get("/proc/self/cgroup"))) {
lines.map(line -> line.split(":"))
.filter(line -> (line.length >= 3))
@ -122,6 +125,25 @@ public class Metrics implements jdk.internal.platform.Metrics {
return null;
}
static Stream<String> readFilePrivileged(Path path) throws IOException {
try {
PrivilegedExceptionAction<Stream<String>> pea = () -> Files.lines(path);
return AccessController.doPrivileged(pea);
} catch (PrivilegedActionException e) {
unwrapIOExceptionAndRethrow(e);
throw new InternalError(e.getCause());
}
}
static void unwrapIOExceptionAndRethrow(PrivilegedActionException pae) throws IOException {
Throwable x = pae.getCause();
if (x instanceof IOException)
throw (IOException) x;
if (x instanceof RuntimeException)
throw (RuntimeException) x;
if (x instanceof Error)
throw (Error) x;
}
/**
* createSubSystem objects and initialize mount points
*/

View File

@ -30,6 +30,9 @@ import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@ -90,14 +93,24 @@ public class SubSystem {
public static String getStringValue(SubSystem subsystem, String parm) {
if (subsystem == null) return null;
try(BufferedReader bufferedReader = Files.newBufferedReader(Paths.get(subsystem.path(), parm))) {
String line = bufferedReader.readLine();
return line;
}
catch (IOException e) {
try {
return subsystem.readStringValue(parm);
} catch (IOException e) {
return null;
}
}
private String readStringValue(String param) throws IOException {
PrivilegedExceptionAction<BufferedReader> pea = () ->
Files.newBufferedReader(Paths.get(path(), param));
try (BufferedReader bufferedReader =
AccessController.doPrivileged(pea)) {
String line = bufferedReader.readLine();
return line;
} catch (PrivilegedActionException e) {
Metrics.unwrapIOExceptionAndRethrow(e);
throw new InternalError(e.getCause());
}
}
public static long getLongValueMatchingLine(SubSystem subsystem,
@ -106,8 +119,8 @@ public class SubSystem {
Function<String, Long> conversion) {
long retval = Metrics.unlimited_minimum + 1; // default unlimited
try {
List<String> lines = Files.readAllLines(Paths.get(subsystem.path(), param));
for (String line: lines) {
List<String> lines = subsystem.readMatchingLines(param);
for (String line : lines) {
if (line.startsWith(match)) {
retval = conversion.apply(line);
break;
@ -119,6 +132,17 @@ public class SubSystem {
return retval;
}
private List<String> readMatchingLines(String param) throws IOException {
try {
PrivilegedExceptionAction<List<String>> pea = () ->
Files.readAllLines(Paths.get(path(), param));
return AccessController.doPrivileged(pea);
} catch (PrivilegedActionException e) {
Metrics.unwrapIOExceptionAndRethrow(e);
throw new InternalError(e.getCause());
}
}
public static long getLongValue(SubSystem subsystem, String parm) {
String strval = getStringValue(subsystem, parm);
return convertStringToLong(strval);
@ -169,7 +193,7 @@ public class SubSystem {
if (subsystem == null) return 0L;
try (Stream<String> lines = Files.lines(Paths.get(subsystem.path(), parm))) {
try (Stream<String> lines = Metrics.readFilePrivileged(Paths.get(subsystem.path(), parm))) {
Optional<String> result = lines.map(line -> line.split(" "))
.filter(line -> (line.length == 2 &&

View File

@ -214,6 +214,8 @@ module java.base {
java.management,
jdk.management.agent,
jdk.internal.jvmstat;
exports jdk.internal.platform to
jdk.management;
exports jdk.internal.ref to
java.desktop;
exports jdk.internal.reflect to

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -258,8 +258,8 @@ class SummaryTab extends Tab {
formatKByteStrings(sunOSMBean.getCommittedVirtualMemorySize());
String[] kbStrings2 =
formatKByteStrings(sunOSMBean.getTotalPhysicalMemorySize(),
sunOSMBean.getFreePhysicalMemorySize(),
formatKByteStrings(sunOSMBean.getTotalMemorySize(),
sunOSMBean.getFreeMemorySize(),
sunOSMBean.getTotalSwapSpaceSize(),
sunOSMBean.getFreeSwapSpaceSize());

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -31,7 +31,7 @@
#include "com_sun_management_internal_OperatingSystemImpl.h"
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0
Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
(JNIEnv *env, jobject dummy)
{
return -1.0;
@ -43,3 +43,17 @@ Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
{
return -1.0;
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
(JNIEnv *env, jobject dummy, jint cpu_number)
{
return -1.0;
}
JNIEXPORT jint JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
(JNIEnv *env, jobject mbean)
{
return -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -198,17 +198,19 @@ static int get_jvmticks(ticks *pticks) {
* This method must be called first, before any data can be gathererd.
*/
int perfInit() {
static int initialized=1;
static int initialized = 0;
if (!initialized) {
int i;
int n = sysconf(_SC_NPROCESSORS_ONLN);
// We need to allocate counters for all CPUs, including ones that
// are currently offline as they could be turned online later.
int n = sysconf(_SC_NPROCESSORS_CONF);
if (n <= 0) {
n = 1;
}
counters.cpus = calloc(n,sizeof(ticks));
counters.nProcs = n;
if (counters.cpus != NULL) {
// For the CPU load
get_totalticks(-1, &counters.cpuTicks);
@ -320,10 +322,10 @@ double get_process_load() {
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0
Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
(JNIEnv *env, jobject dummy)
{
if(perfInit() == 0) {
if (perfInit() == 0) {
return get_cpu_load(-1);
} else {
return -1.0;
@ -334,9 +336,31 @@ JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
(JNIEnv *env, jobject dummy)
{
if(perfInit() == 0) {
if (perfInit() == 0) {
return get_process_load();
} else {
return -1.0;
}
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
(JNIEnv *env, jobject mbean, jint cpu_number)
{
if (perfInit() == 0 && cpu_number >= 0 && cpu_number < counters.nProcs) {
return get_cpu_load(cpu_number);
} else {
return -1.0;
}
}
JNIEXPORT jint JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
(JNIEnv *env, jobject mbean)
{
if (perfInit() == 0) {
return counters.nProcs;
} else {
return -1;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@
#include "jvm.h"
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0
Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
(JNIEnv *env, jobject dummy)
{
// This code is influenced by the darwin top source
@ -159,3 +159,17 @@ Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
return cpu;
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
(JNIEnv *env, jobject dummy, jint cpu_number)
{
return -1.0;
}
JNIEXPORT jint JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
(JNIEnv *env, jobject mbean)
{
return -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,12 @@ package com.sun.management;
* on which the Java virtual machine is running.
*
* <p>
* This interface provides information about the operating environment
* on which the Java virtual machine is running. That might be a native
* operating system, a virtualized operating system environment, or a
* container-managed environment.
*
* <p>
* The {@code OperatingSystemMXBean} object returned by
* {@link java.lang.management.ManagementFactory#getOperatingSystemMXBean()}
* is an instance of the implementation class of this interface
@ -82,16 +88,46 @@ public interface OperatingSystemMXBean extends
/**
* Returns the amount of free physical memory in bytes.
*
* @deprecated Use {@link #getFreeMemorySize()} instead of
* this historically named method.
*
* @implSpec This implementation must return the same value
* as {@link #getFreeMemorySize()}.
*
* @return the amount of free physical memory in bytes.
*/
public long getFreePhysicalMemorySize();
@Deprecated(since="14")
public default long getFreePhysicalMemorySize() { return getFreeMemorySize(); }
/**
* Returns the amount of free memory in bytes.
*
* @return the amount of free memory in bytes.
* @since 14
*/
public long getFreeMemorySize();
/**
* Returns the total amount of physical memory in bytes.
*
* @deprecated Use {@link #getMemorySize()} instead of
* this historically named method.
*
* @implSpec This implementation must return the same value
* as {@link #getMemorySize()}.
*
* @return the total amount of physical memory in bytes.
*/
public long getTotalPhysicalMemorySize();
@Deprecated(since="14")
public default long getTotalPhysicalMemorySize() { return getTotalMemorySize(); }
/**
* Returns the total amount of memory in bytes.
*
* @return the total amount of memory in bytes.
* @since 14
*/
public long getTotalMemorySize();
/**
* Returns the "recent cpu usage" for the whole system. This value is a
@ -103,11 +139,34 @@ public interface OperatingSystemMXBean extends
* If the system recent cpu usage is not available, the method returns a
* negative value.
*
* @deprecated Use {@link #getCpuLoad()} instead of
* this historically named method.
*
* @implSpec This implementation must return the same value
* as {@link #getCpuLoad()}.
*
* @return the "recent cpu usage" for the whole system; a negative
* value if not available.
* @since 1.7
*/
public double getSystemCpuLoad();
@Deprecated(since="14")
public default double getSystemCpuLoad() { return getCpuLoad(); }
/**
* Returns the "recent cpu usage" for the operating environment. This value
* is a double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs
* were idle during the recent period of time observed, while a value
* of 1.0 means that all CPUs were actively running 100% of the time
* during the recent period being observed. All values betweens 0.0 and
* 1.0 are possible depending of the activities going on.
* If the recent cpu usage is not available, the method returns a
* negative value.
*
* @return the "recent cpu usage" for the whole operating environment;
* a negative value if not available.
* @since 14
*/
public double getCpuLoad();
/**
* Returns the "recent cpu usage" for the Java Virtual Machine process.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -226,7 +226,7 @@ double get_process_load(void) {
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0
Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
(JNIEnv *env, jobject dummy)
{
return get_cpu_load(-1);
@ -239,3 +239,16 @@ Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0
return get_process_load();
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSingleCpuLoad0
(JNIEnv *env, jobject mbean, jint cpu_number)
{
return -1.0;
}
JNIEXPORT jint JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getHostConfiguredCpuCount0
(JNIEnv *env, jobject mbean)
{
return -1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,8 +25,11 @@
package com.sun.management.internal;
import jdk.internal.platform.Metrics;
import sun.management.BaseOperatingSystemImpl;
import sun.management.VMManagement;
import java.util.concurrent.TimeUnit;
/**
* Implementation class for the operating system.
* Standard and committed hotspot-specific metrics if any.
@ -37,8 +40,12 @@ import sun.management.VMManagement;
class OperatingSystemImpl extends BaseOperatingSystemImpl
implements com.sun.management.UnixOperatingSystemMXBean {
private static final int MAX_ATTEMPTS_NUMBER = 10;
private final Metrics containerMetrics;
OperatingSystemImpl(VMManagement vm) {
super(vm);
this.containerMetrics = jdk.internal.platform.Container.metrics();
}
public long getCommittedVirtualMemorySize() {
@ -46,10 +53,39 @@ class OperatingSystemImpl extends BaseOperatingSystemImpl
}
public long getTotalSwapSpaceSize() {
if (containerMetrics != null) {
long limit = containerMetrics.getMemoryAndSwapLimit();
// The memory limit metrics is not available if JVM runs on Linux host (not in a docker container)
// or if a docker container was started without specifying a memory limit (without '--memory='
// Docker option). In latter case there is no limit on how much memory the container can use and
// it can use as much memory as the host's OS allows.
long memLimit = containerMetrics.getMemoryLimit();
if (limit >= 0 && memLimit >= 0) {
return limit - memLimit;
}
}
return getTotalSwapSpaceSize0();
}
public long getFreeSwapSpaceSize() {
if (containerMetrics != null) {
long memSwapLimit = containerMetrics.getMemoryAndSwapLimit();
long memLimit = containerMetrics.getMemoryLimit();
if (memSwapLimit >= 0 && memLimit >= 0) {
for (int attempt = 0; attempt < MAX_ATTEMPTS_NUMBER; attempt++) {
long memSwapUsage = containerMetrics.getMemoryAndSwapUsage();
long memUsage = containerMetrics.getMemoryUsage();
if (memSwapUsage > 0 && memUsage > 0) {
// We read "memory usage" and "memory and swap usage" not atomically,
// and it's possible to get the negative value when subtracting these two.
// If this happens just retry the loop for a few iterations.
if ((memSwapUsage - memUsage) >= 0) {
return memSwapLimit - memLimit - (memSwapUsage - memUsage);
}
}
}
}
}
return getFreeSwapSpaceSize0();
}
@ -57,12 +93,25 @@ class OperatingSystemImpl extends BaseOperatingSystemImpl
return getProcessCpuTime0();
}
public long getFreePhysicalMemorySize() {
return getFreePhysicalMemorySize0();
public long getFreeMemorySize() {
if (containerMetrics != null) {
long usage = containerMetrics.getMemoryUsage();
long limit = containerMetrics.getMemoryLimit();
if (usage > 0 && limit >= 0) {
return limit - usage;
}
}
return getFreeMemorySize0();
}
public long getTotalPhysicalMemorySize() {
return getTotalPhysicalMemorySize0();
public long getTotalMemorySize() {
if (containerMetrics != null) {
long limit = containerMetrics.getMemoryLimit();
if (limit >= 0) {
return limit;
}
}
return getTotalMemorySize0();
}
public long getOpenFileDescriptorCount() {
@ -73,25 +122,73 @@ class OperatingSystemImpl extends BaseOperatingSystemImpl
return getMaxFileDescriptorCount0();
}
public double getSystemCpuLoad() {
return getSystemCpuLoad0();
public double getCpuLoad() {
if (containerMetrics != null) {
long quota = containerMetrics.getCpuQuota();
if (quota > 0) {
long periodLength = containerMetrics.getCpuPeriod();
long numPeriods = containerMetrics.getCpuNumPeriods();
long usageNanos = containerMetrics.getCpuUsage();
if (periodLength > 0 && numPeriods > 0 && usageNanos > 0) {
long elapsedNanos = TimeUnit.MICROSECONDS.toNanos(periodLength * numPeriods);
double systemLoad = (double) usageNanos / elapsedNanos;
// Ensure the return value is in the range 0.0 -> 1.0
systemLoad = Math.max(0.0, systemLoad);
systemLoad = Math.min(1.0, systemLoad);
return systemLoad;
}
return -1;
} else {
// If CPU quotas are not active then find the average system load for
// all online CPUs that are allowed to run this container.
// If the cpuset is the same as the host's one there is no need to iterate over each CPU
if (isCpuSetSameAsHostCpuSet()) {
return getCpuLoad0();
} else {
int[] cpuSet = containerMetrics.getEffectiveCpuSetCpus();
if (cpuSet != null && cpuSet.length > 0) {
double systemLoad = 0.0;
for (int cpu : cpuSet) {
double cpuLoad = getSingleCpuLoad0(cpu);
if (cpuLoad < 0) {
return -1;
}
systemLoad += cpuLoad;
}
return systemLoad / cpuSet.length;
}
return -1;
}
}
}
return getCpuLoad0();
}
public double getProcessCpuLoad() {
return getProcessCpuLoad0();
}
private boolean isCpuSetSameAsHostCpuSet() {
if (containerMetrics != null) {
return containerMetrics.getCpuSetCpus().length == getHostConfiguredCpuCount0();
}
return false;
}
/* native methods */
private native long getCommittedVirtualMemorySize0();
private native long getFreePhysicalMemorySize0();
private native long getFreeMemorySize0();
private native long getFreeSwapSpaceSize0();
private native long getMaxFileDescriptorCount0();
private native long getOpenFileDescriptorCount0();
private native long getProcessCpuTime0();
private native double getProcessCpuLoad0();
private native double getSystemCpuLoad0();
private native long getTotalPhysicalMemorySize0();
private native double getCpuLoad0();
private native long getTotalMemorySize0();
private native long getTotalSwapSpaceSize0();
private native double getSingleCpuLoad0(int cpuNum);
private native int getHostConfiguredCpuCount0();
static {
initialize0();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -306,7 +306,7 @@ Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuTime0
}
JNIEXPORT jlong JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0
Java_com_sun_management_internal_OperatingSystemImpl_getFreeMemorySize0
(JNIEnv *env, jobject mbean)
{
#ifdef __APPLE__
@ -340,7 +340,7 @@ Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0
}
JNIEXPORT jlong JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getTotalPhysicalMemorySize0
Java_com_sun_management_internal_OperatingSystemImpl_getTotalMemorySize0
(JNIEnv *env, jobject mbean)
{
#ifdef _ALLBSD_SOURCE

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -70,18 +70,18 @@ class OperatingSystemImpl extends BaseOperatingSystemImpl
}
@Override
public long getFreePhysicalMemorySize() {
return getFreePhysicalMemorySize0();
public long getFreeMemorySize() {
return getFreeMemorySize0();
}
@Override
public long getTotalPhysicalMemorySize() {
return getTotalPhysicalMemorySize0();
public long getTotalMemorySize() {
return getTotalMemorySize0();
}
@Override
public double getSystemCpuLoad() {
return getSystemCpuLoad0();
public double getCpuLoad() {
return getCpuLoad0();
}
@Override
@ -91,12 +91,12 @@ class OperatingSystemImpl extends BaseOperatingSystemImpl
/* native methods */
private native long getCommittedVirtualMemorySize0();
private native long getFreePhysicalMemorySize0();
private native long getFreeMemorySize0();
private native long getFreeSwapSpaceSize0();
private native double getProcessCpuLoad0();
private native long getProcessCpuTime0();
private native double getSystemCpuLoad0();
private native long getTotalPhysicalMemorySize0();
private native double getCpuLoad0();
private native long getTotalMemorySize0();
private native long getTotalSwapSpaceSize0();
static {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -134,7 +134,7 @@ Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuTime0
}
JNIEXPORT jlong JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0
Java_com_sun_management_internal_OperatingSystemImpl_getFreeMemorySize0
(JNIEnv *env, jobject mbean)
{
MEMORYSTATUSEX ms;
@ -144,7 +144,7 @@ Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0
}
JNIEXPORT jlong JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getTotalPhysicalMemorySize0
Java_com_sun_management_internal_OperatingSystemImpl_getTotalMemorySize0
(JNIEnv *env, jobject mbean)
{
MEMORYSTATUSEX ms;
@ -1349,7 +1349,7 @@ perfGetCPULoad(int which) {
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0
Java_com_sun_management_internal_OperatingSystemImpl_getCpuLoad0
(JNIEnv *env, jobject dummy)
{
return perfGetCPULoad(-1);

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, Red Hat Inc. All rights reserved.
* 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.
*
* 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.
*/
import com.sun.management.OperatingSystemMXBean;
import java.lang.management.ManagementFactory;
public class CheckOperatingSystemMXBean {
public static void main(String[] args) {
System.out.println("Checking OperatingSystemMXBean");
OperatingSystemMXBean osBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
System.out.println(String.format("Runtime.availableProcessors: %d", Runtime.getRuntime().availableProcessors()));
System.out.println(String.format("OperatingSystemMXBean.getAvailableProcessors: %d", osBean.getAvailableProcessors()));
System.out.println(String.format("OperatingSystemMXBean.getTotalMemorySize: %d", osBean.getTotalMemorySize()));
System.out.println(String.format("OperatingSystemMXBean.getTotalPhysicalMemorySize: %d", osBean.getTotalPhysicalMemorySize()));
System.out.println(String.format("OperatingSystemMXBean.getFreeMemorySize: %d", osBean.getFreeMemorySize()));
System.out.println(String.format("OperatingSystemMXBean.getFreePhysicalMemorySize: %d", osBean.getFreePhysicalMemorySize()));
System.out.println(String.format("OperatingSystemMXBean.getTotalSwapSpaceSize: %d", osBean.getTotalSwapSpaceSize()));
System.out.println(String.format("OperatingSystemMXBean.getFreeSwapSpaceSize: %d", osBean.getFreeSwapSpaceSize()));
System.out.println(String.format("OperatingSystemMXBean.getCpuLoad: %f", osBean.getCpuLoad()));
System.out.println(String.format("OperatingSystemMXBean.getSystemCpuLoad: %f", osBean.getSystemCpuLoad()));
}
}

View File

@ -30,6 +30,7 @@
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @build PrintContainerInfo CheckOperatingSystemMXBean
* @run driver TestCPUAwareness
*/
import java.util.List;
@ -76,8 +77,18 @@ public class TestCPUAwareness {
testCpuQuotaAndPeriod(150*1000, 100*1000);
testCpuQuotaAndPeriod(400*1000, 100*1000);
testOperatingSystemMXBeanAwareness("0.5", "1");
testOperatingSystemMXBeanAwareness("1.0", "1");
if (availableCPUs > 2) {
testOperatingSystemMXBeanAwareness("1.2", "2");
testOperatingSystemMXBeanAwareness("1.8", "2");
testOperatingSystemMXBeanAwareness("2.0", "2");
}
} finally {
DockerTestUtils.removeDockerImage(imageName);
if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
DockerTestUtils.removeDockerImage(imageName);
}
}
}
@ -206,4 +217,22 @@ public class TestCPUAwareness {
.shouldMatch("CPU Shares is.*" + shares)
.shouldMatch("active_processor_count.*" + expectedAPC);
}
private static void testOperatingSystemMXBeanAwareness(String cpuAllocation, String expectedCpus) throws Exception {
Common.logNewTestCase("Check OperatingSystemMXBean");
DockerRunOptions opts = Common.newOpts(imageName, "CheckOperatingSystemMXBean")
.addDockerOpts(
"--cpus", cpuAllocation
);
DockerTestUtils.dockerRunJava(opts)
.shouldHaveExitValue(0)
.shouldContain("Checking OperatingSystemMXBean")
.shouldContain("Runtime.availableProcessors: " + expectedCpus)
.shouldContain("OperatingSystemMXBean.getAvailableProcessors: " + expectedCpus)
.shouldMatch("OperatingSystemMXBean\\.getSystemCpuLoad: [0-9]+\\.[0-9]+")
.shouldMatch("OperatingSystemMXBean\\.getCpuLoad: [0-9]+\\.[0-9]+")
;
}
}

View File

@ -30,7 +30,7 @@
* @modules java.base/jdk.internal.misc
* java.management
* jdk.jartool/sun.tools.jar
* @build AttemptOOM sun.hotspot.WhiteBox PrintContainerInfo
* @build AttemptOOM sun.hotspot.WhiteBox PrintContainerInfo CheckOperatingSystemMXBean
* @run driver ClassFileInstaller -jar whitebox.jar sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run driver TestMemoryAwareness
*/
@ -62,8 +62,22 @@ public class TestMemoryAwareness {
// Add extra 10 Mb to allocator limit, to be sure to cause OOM
testOOM("256m", 256 + 10);
testOperatingSystemMXBeanAwareness(
"100M", Integer.toString(((int) Math.pow(2, 20)) * 100),
"150M", Integer.toString(((int) Math.pow(2, 20)) * (150 - 100))
);
testOperatingSystemMXBeanAwareness(
"128M", Integer.toString(((int) Math.pow(2, 20)) * 128),
"256M", Integer.toString(((int) Math.pow(2, 20)) * (256 - 128))
);
testOperatingSystemMXBeanAwareness(
"1G", Integer.toString(((int) Math.pow(2, 20)) * 1024),
"1500M", Integer.toString(((int) Math.pow(2, 20)) * (1500 - 1024))
);
} finally {
DockerTestUtils.removeDockerImage(imageName);
if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) {
DockerTestUtils.removeDockerImage(imageName);
}
}
}
@ -120,4 +134,26 @@ public class TestMemoryAwareness {
.shouldContain("java.lang.OutOfMemoryError");
}
private static void testOperatingSystemMXBeanAwareness(String memoryAllocation, String expectedMemory,
String swapAllocation, String expectedSwap) throws Exception {
Common.logNewTestCase("Check OperatingSystemMXBean");
DockerRunOptions opts = Common.newOpts(imageName, "CheckOperatingSystemMXBean")
.addDockerOpts(
"--memory", memoryAllocation,
"--memory-swap", swapAllocation
);
DockerTestUtils.dockerRunJava(opts)
.shouldHaveExitValue(0)
.shouldContain("Checking OperatingSystemMXBean")
.shouldContain("OperatingSystemMXBean.getTotalPhysicalMemorySize: " + expectedMemory)
.shouldMatch("OperatingSystemMXBean\\.getFreePhysicalMemorySize: [1-9][0-9]+")
.shouldContain("OperatingSystemMXBean.getTotalMemorySize: " + expectedMemory)
.shouldMatch("OperatingSystemMXBean\\.getFreeMemorySize: [1-9][0-9]+")
.shouldContain("OperatingSystemMXBean.getTotalSwapSpaceSize: " + expectedSwap)
.shouldMatch("OperatingSystemMXBean\\.getFreeSwapSpaceSize: [1-9][0-9]+")
;
}
}