8226575: OperatingSystemMXBean should be made container aware
Reviewed-by: dholmes, bobv, mchung, sspitsyn
This commit is contained in:
parent
efdf413a20
commit
7b82266a15
@ -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
|
||||
*/
|
||||
|
@ -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 &&
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
@ -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]+")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
@ -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]+")
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user