org.jppf.utils.SystemUtils Maven / Gradle / Ivy
Show all versions of jppf-common Show documentation
/*
* JPPF.
* Copyright (C) 2005-2015 JPPF Team.
* http://www.jppf.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jppf.utils;
import static org.jppf.utils.PropertyType.*;
import java.io.File;
import java.net.InetAddress;
import java.security.*;
import java.util.*;
import org.slf4j.*;
//import java.lang.management.*;
/**
* Collection of utility methods used as a convenience for retrieving
* JVM-level or System-level information.
* @author Laurent Cohen
*/
public final class SystemUtils {
/**
* Logger for this class.
*/
private static Logger log = LoggerFactory.getLogger(SystemUtils.class);
/**
* Determines whether the debug level is enabled in the logging configuration, without the cost of a method call.
*/
//private static boolean debugEnabled = LoggingUtils.isDebugEnabled(log);
private static boolean debugEnabled = true;
/**
* Singleton holding the unchanging system properties.
*/
private static TypedProperties systemProps = null;
/**
* A map of the environment properties.
*/
private static TypedProperties env = null;
/**
* A map of the network configuration.
*/
private static TypedProperties network = null;
/**
* A map of the physical RAM information.
*/
private static TypedProperties os = null;
/**
* Windows OS.
*/
private static final int WINDOWS_OS = 1;
/**
* X11 based OS.
*/
private static final int X11_OS = 2;
/**
* The MAC based OS.
*/
private static final int MAC_OS = 3;
/**
* Unknown or unsupported OS.
*/
private static final int UNKNOWN_OS = -1;
/**
* The type of this host's OS.
*/
private static final int OS_TYPE = determineOSType();
/**
* Holds and manages the shutdown hooks set on the JVM.
*/
private static Map shutdownHooks = new Hashtable<>();
/**
* Instantiation of this class is not permitted.
*/
private SystemUtils() {
}
/**
* Return a set of properties guaranteed to always be part of those returned by
* {@link java.lang.System#getProperties() System.getProperties()}.
* @return the properties as a TypedProperties
instance.
*/
public static synchronized TypedProperties getSystemProperties() {
if (systemProps == null) {
TypedProperties props = new TypedProperties();
addOtherSystemProperties(props);
systemProps = props;
}
return systemProps;
}
/**
* Add system properties whose name is not known in advance.
* @param props the TypedProperties instance to add the system properties to.
*/
private static void addOtherSystemProperties(final TypedProperties props) {
try {
// run as privileged so we don't have to set write access on all properties in the security policy file.
Properties sysProps = AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Properties run() {
return System.getProperties();
}
});
Enumeration en = sysProps.propertyNames();
while (en.hasMoreElements()) {
String name = (String) en.nextElement();
try {
if (!props.contains(name)) props.setProperty(name, System.getProperty(name));
} catch(SecurityException e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.info(e.getMessage());
}
}
} catch(SecurityException e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.info(e.getMessage());
}
}
/**
* Get information about the number of processors available to the JVM and the JVM memory usage.
* @return a TypedProperties
instance holding the requested information.
*/
public static TypedProperties getRuntimeInformation() {
TypedProperties props = new TypedProperties();
try {
props.setInt("availableProcessors", Runtime.getRuntime().availableProcessors());
props.setLong("freeMemory", Runtime.getRuntime().freeMemory());
props.setLong("totalMemory", Runtime.getRuntime().totalMemory());
props.setLong("maxMemory", Runtime.getRuntime().maxMemory());
if (ManagementUtils.isManagementAvailable()) {
Object mbeanServer = ManagementUtils.getPlatformServer();
String mbeanName = "java.lang:type=Runtime";
String s = String.valueOf(ManagementUtils.getAttribute(mbeanServer, mbeanName, "StartTime"));
props.setProperty("startTime", s);
s = String.valueOf(ManagementUtils.getAttribute(mbeanServer, mbeanName, "Uptime"));
props.setProperty("uptime", s);
s = String.valueOf(ManagementUtils.getAttribute(mbeanServer, mbeanName, "InputArguments"));
props.setProperty("inputArgs", s);
}
} catch(Exception e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.info(e.getMessage());
}
return props;
}
/**
* Get storage information about the file system roots available on the current host.
* This method populates a {@link TypedProperties} object with root name, free space,
* total space and usable space information for each root.
* An example root name would be "C:\" for a Windows system and "/" for a Unix system.
* @return TypedProperties object with storage information.
*/
public static synchronized TypedProperties getStorageInformation() {
TypedProperties props = new TypedProperties();
File[] roots = File.listRoots();
props.setInt("host.roots.number", roots == null ? 0 : roots.length);
if ((roots == null) || (roots.length <= 0)) return props;
StringBuilder sb = new StringBuilder();
for (int i=0; i 0) sb.append(' ');
String s = roots[i].getCanonicalPath();
sb.append(s);
String prefix = "root." + i;
props.setProperty(prefix + ".name", s);
props.setLong(prefix + ".space.total", roots[i].getTotalSpace());
props.setLong(prefix + ".space.free", roots[i].getFreeSpace());
props.setLong(prefix + ".space.usable", roots[i].getUsableSpace());
} catch(Exception e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.warn(e.getMessage());
}
}
props.setProperty("host.roots.names", sb.toString());
return props;
}
/**
* Get a map of the environment variables.
* @return a mapping of environment variables to their value.
*/
public static synchronized TypedProperties getEnvironment() {
if (env == null) {
env = new TypedProperties();
try {
Map props = System.getenv();
for (Map.Entry entry: props.entrySet()) {
env.setProperty(entry.getKey(), entry.getValue());
}
} catch(SecurityException e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.info(e.getMessage());
}
}
return env;
}
/**
* Get a map of the environment variables.
* @return a mapping of environment variables to their value.
*/
public static synchronized TypedProperties getNetwork() {
if (network == null) {
network = new TypedProperties();
try {
network.setProperty("ipv4.addresses", formatAddresses(NetworkUtils.getIPV4Addresses()));
network.setProperty("ipv6.addresses", formatAddresses(NetworkUtils.getIPV6Addresses()));
} catch(SecurityException e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.info(e.getMessage());
}
}
return network;
}
/**
* Format a list of InetAddress.
* @param addresses a List of InetAddress
instances.
* @return a string containing a space-separated list of hostname|ip_address pairs.
*/
private static String formatAddresses(final List extends InetAddress> addresses) {
StringBuilder sb = new StringBuilder();
for (InetAddress addr: addresses) {
String name = addr.getHostName();
String ip = addr.getHostAddress();
if (sb.length() > 0) sb.append(' ');
sb.append(name).append('|').append(ip);
}
return sb.toString();
}
/**
* Compute the maximum memory currently available for the Java heap.
* @return the maximum number of free bytes in the heap.
*/
public static long maxFreeHeap() {
Runtime rt = Runtime.getRuntime();
return rt.maxMemory() - (rt.totalMemory() - rt.freeMemory());
}
/**
* Determine the type of this host's operating system, based on the value
* of the system property "os.name".
* @return an int value identifying the type of OS.
*/
private static int determineOSType() {
String name = System.getProperty("os.name");
if (StringUtils.startsWithOneOf(name, true, "Linux", "SunOS", "Solaris", "FreeBSD", "OpenBSD")) return X11_OS;
else if (StringUtils.startsWithOneOf(name, true, "Mac", "Darwin")) return MAC_OS;
else if (name.startsWith("Windows") && !name.startsWith("Windows CE")) return WINDOWS_OS;
return UNKNOWN_OS;
}
/**
* Determine whether the current OS is Windows.
* @return true if the system is Windows, false otherwise.
*/
public static boolean isWindows() {
return OS_TYPE == WINDOWS_OS;
}
/**
* Determine whether the current OS is X11-based.
* @return true if the system is X11, false otherwise.
*/
public static boolean isX11() {
return OS_TYPE == X11_OS;
}
/**
* Determine whether the current OS is Mac-based.
* @return true if the system is Mac-based, false otherwise.
*/
public static boolean isMac() {
return OS_TYPE == MAC_OS;
}
/**
* Return the current process ID.
* @return the pid as an int, or -1 if the pid could not be obtained.
*/
public static int getPID() {
int pid = -1;
// we expect the name to be in '@hostname' format - this is JVM dependent
//String name = ManagementFactory.getRuntimeMXBean().getName();
try {
if (ManagementUtils.isManagementAvailable()) {
String name = String.valueOf(ManagementUtils.getAttribute(ManagementUtils.getPlatformServer(), "java.lang:type=Runtime", "Name"));
int idx = name.indexOf('@');
if (idx >= 0) {
String sub = name.substring(0, idx);
try {
pid = Integer.valueOf(sub);
if (debugEnabled) log.debug("process name=" + name + ", pid=" + pid);
} catch (Exception e) {
String msg = "could not parse '" + sub +"' into a valid integer pid : " + ExceptionUtils.getMessage(e);
if (debugEnabled) log.debug(msg, e);
else log.warn(msg);
}
}
}
} catch (Exception e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.warn(e.getMessage());
}
return pid;
}
/**
* Add the specified shutdown hook with the specified key.
* @param key the hokk's key.
* @param hook the shutdown hook to add.
*/
public static void addShutdownHook(final String key, final Thread hook) {
shutdownHooks.put(key, hook);
Runtime.getRuntime().addShutdownHook(hook);
}
/**
* Add the specified shutdown hook with the specified key.
* @param key the hokk's key.
*/
public static void removeShutdownHook(final String key) {
Thread hook = shutdownHooks.remove(key);
if (hook != null) Runtime.getRuntime().removeShutdownHook(hook);
}
/**
* Prints the JPPF process id and uuid to {@code System.out}.
* @param component the JPPF component type: driver, node or client.
* @param uuid the component uuid.
*/
public static void printPidAndUuid(final String component, final String uuid) {
StringBuilder sb = new StringBuilder(component == null ? "" : component);
int pid = getPID();
if (pid >= 0) sb = sb.append(" process id: ").append(pid).append(',');
sb.append(" uuid: ").append(uuid);
System.out.println(sb.toString());
}
/**
* Get the available physical ram information for the local machine.
* @return the memory information eelements as a {@link TypedProperties} instance.
*/
public static TypedProperties getOS() {
if (os == null) {
os = new TypedProperties();
if (ManagementUtils.isManagementAvailable()) {
try {
capture("TotalPhysicalMemorySize", os, LONG);
capture("FreePhysicalMemorySize", os, LONG);
capture("TotalSwapSpaceSize", os, LONG);
capture("FreeSwapSpaceSize", os, LONG);
capture("CommittedVirtualMemorySize", os, LONG);
//capture("ProcessCpuLoad", os, DOUBLE);
capture("ProcessCpuTime", os, LONG);
//capture("SystemCpuLoad", os, DOUBLE);
capture("Name", os, STRING);
capture("Version", os, STRING);
capture("Arch", os, STRING);
capture("AvailableProcessors", os, INT);
//capture("SystemLoadAverage", os, DOUBLE);
} catch(Exception e) {
if (debugEnabled) log.debug(e.getMessage(), e);
else log.info(e.getMessage());
}
}
}
return os;
}
/**
* Capture the specified {@code long} attribute into the specified TypedProperties object.
* @param name the attribute name.
* @param props the properties holding the attribute and its value.
* @param type the type of the attribute.
*/
private static void capture(final String name, final TypedProperties props, final PropertyType type) {
if (!ManagementUtils.isManagementAvailable()) return;
Object value = null;
try {
value = ManagementUtils.getAttribute(ManagementUtils.getPlatformServer(), "java.lang:type=OperatingSystem", name);
} catch(Exception ignore) {
return;
}
switch(type) {
case INT:
props.setInt("os." + name, value != null ? (Integer) value : -1);
break;
case LONG:
props.setLong("os." + name, value != null ? (Long) value : -1L);
break;
case DOUBLE:
props.setDouble("os." + name, value != null ? (Double) value : -1d);
break;
case STRING:
props.setString("os." + name, value != null ? (String) value : "");
break;
}
}
}