1 /* 2 * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.management.internal; 27 28 import jdk.internal.platform.Metrics; 29 import sun.management.BaseOperatingSystemImpl; 30 import sun.management.VMManagement; 31 32 import java.util.concurrent.TimeUnit; 33 /** 34 * Implementation class for the operating system. 35 * Standard and committed hotspot-specific metrics if any. 36 * 37 * ManagementFactory.getOperatingSystemMXBean() returns an instance 38 * of this class. 39 */ 40 class OperatingSystemImpl extends BaseOperatingSystemImpl 41 implements com.sun.management.UnixOperatingSystemMXBean { 42 43 private static final int MAX_ATTEMPTS_NUMBER = 10; 44 private final Metrics containerMetrics; 45 46 OperatingSystemImpl(VMManagement vm) { 47 super(vm); 48 this.containerMetrics = jdk.internal.platform.Container.metrics(); 49 } 50 51 public long getCommittedVirtualMemorySize() { 52 return getCommittedVirtualMemorySize0(); 53 } 54 55 public long getTotalSwapSpaceSize() { 56 if (containerMetrics != null) { 57 long limit = containerMetrics.getMemoryAndSwapLimit(); 58 // The memory limit metrics is not available if JVM runs on Linux host (not in a docker container) 59 // or if a docker container was started without specifying a memory limit (without '--memory=' 60 // Docker option). In latter case there is no limit on how much memory the container can use and 61 // it can use as much memory as the host's OS allows. 62 long memLimit = containerMetrics.getMemoryLimit(); 63 if (limit >= 0 && memLimit >= 0) { 64 return limit - memLimit; 65 } 66 } 67 return getTotalSwapSpaceSize0(); 68 } 69 70 public long getFreeSwapSpaceSize() { 71 if (containerMetrics != null) { 72 long memSwapLimit = containerMetrics.getMemoryAndSwapLimit(); 73 long memLimit = containerMetrics.getMemoryLimit(); 74 if (memSwapLimit >= 0 && memLimit >= 0) { 75 for (int attempt = 0; attempt < MAX_ATTEMPTS_NUMBER; attempt++) { 76 long memSwapUsage = containerMetrics.getMemoryAndSwapUsage(); 77 long memUsage = containerMetrics.getMemoryUsage(); 78 if (memSwapUsage > 0 && memUsage > 0) { 79 // We read "memory usage" and "memory and swap usage" not atomically, 80 // and it's possible to get the negative value when subtracting these two. 81 // If this happens just retry the loop for a few iterations. 82 if ((memSwapUsage - memUsage) >= 0) { 83 return memSwapLimit - memLimit - (memSwapUsage - memUsage); 84 } 85 } 86 } 87 } 88 } 89 return getFreeSwapSpaceSize0(); 90 } 91 92 public long getProcessCpuTime() { 93 return getProcessCpuTime0(); 94 } 95 96 public long getFreeMemorySize() { 97 if (containerMetrics != null) { 98 long usage = containerMetrics.getMemoryUsage(); 99 long limit = containerMetrics.getMemoryLimit(); 100 if (usage > 0 && limit >= 0) { 101 return limit - usage; 102 } 103 } 104 return getFreeMemorySize0(); 105 } 106 107 public long getTotalMemorySize() { 108 if (containerMetrics != null) { 109 long limit = containerMetrics.getMemoryLimit(); 110 if (limit >= 0) { 111 return limit; 112 } 113 } 114 return getTotalMemorySize0(); 115 } 116 117 public long getOpenFileDescriptorCount() { 118 return getOpenFileDescriptorCount0(); 119 } 120 121 public long getMaxFileDescriptorCount() { 122 return getMaxFileDescriptorCount0(); 123 } 124 125 public double getCpuLoad() { 126 if (containerMetrics != null) { 127 long quota = containerMetrics.getCpuQuota(); 128 if (quota > 0) { 129 long periodLength = containerMetrics.getCpuPeriod(); 130 long numPeriods = containerMetrics.getCpuNumPeriods(); 131 long usageNanos = containerMetrics.getCpuUsage(); 132 if (periodLength > 0 && numPeriods > 0 && usageNanos > 0) { 133 long elapsedNanos = TimeUnit.MICROSECONDS.toNanos(periodLength * numPeriods); 134 double systemLoad = (double) usageNanos / elapsedNanos; 135 // Ensure the return value is in the range 0.0 -> 1.0 136 systemLoad = Math.max(0.0, systemLoad); 137 systemLoad = Math.min(1.0, systemLoad); 138 return systemLoad; 139 } 140 return -1; 141 } else { 142 // If CPU quotas are not active then find the average system load for 143 // all online CPUs that are allowed to run this container. 144 145 // If the cpuset is the same as the host's one there is no need to iterate over each CPU 146 if (isCpuSetSameAsHostCpuSet()) { 147 return getCpuLoad0(); 148 } else { 149 int[] cpuSet = containerMetrics.getEffectiveCpuSetCpus(); 150 if (cpuSet != null && cpuSet.length > 0) { 151 double systemLoad = 0.0; 152 for (int cpu : cpuSet) { 153 double cpuLoad = getSingleCpuLoad0(cpu); 154 if (cpuLoad < 0) { 155 return -1; 156 } 157 systemLoad += cpuLoad; 158 } 159 return systemLoad / cpuSet.length; 160 } 161 return -1; 162 } 163 } 164 } 165 return getCpuLoad0(); 166 } 167 168 public double getProcessCpuLoad() { 169 return getProcessCpuLoad0(); 170 } 171 172 private boolean isCpuSetSameAsHostCpuSet() { 173 if (containerMetrics != null) { 174 return containerMetrics.getCpuSetCpus().length == getHostConfiguredCpuCount0(); 175 } 176 return false; 177 } 178 179 /* native methods */ 180 private native long getCommittedVirtualMemorySize0(); 181 private native long getFreeMemorySize0(); 182 private native long getFreeSwapSpaceSize0(); 183 private native long getMaxFileDescriptorCount0(); 184 private native long getOpenFileDescriptorCount0(); 185 private native long getProcessCpuTime0(); 186 private native double getProcessCpuLoad0(); 187 private native double getCpuLoad0(); 188 private native long getTotalMemorySize0(); 189 private native long getTotalSwapSpaceSize0(); 190 private native double getSingleCpuLoad0(int cpuNum); 191 private native int getHostConfiguredCpuCount0(); 192 193 static { 194 initialize0(); 195 } 196 197 private static native void initialize0(); 198 }