obtenir des informations système au niveau du système D'exploitation
Je suis en train de construire une application Java qui pourrait finir par être exécutée sur de nombreuses plates-formes différentes, mais principalement des variantes de Solaris, Linux et Windows.
Quelqu'un a-t-il réussi à extraire des informations telles que l'espace disque actuel utilisé, l'utilisation du processeur et la mémoire utilisée dans le système d'exploitation sous-jacent? Qu'en est-il de ce que L'application Java elle-même consomme?
De préférence, je voudrais obtenir cette information sans utiliser JNI.
14 réponses
Vous pouvez obtenir des informations de mémoire limitées de la classe D'exécution. Ce n'est vraiment pas exactement ce que vous cherchez, mais j'ai pensé que je le fournirais par souci d'exhaustivité. Voici un petit exemple. Edit: vous pouvez également obtenir des informations sur l'utilisation du disque à partir de la classe java.Io.File. L'utilisation de L'espace disque nécessite Java 1.6 ou supérieur.
public class Main {
public static void main(String[] args) {
/* Total number of processors or cores available to the JVM */
System.out.println("Available processors (cores): " +
Runtime.getRuntime().availableProcessors());
/* Total amount of free memory available to the JVM */
System.out.println("Free memory (bytes): " +
Runtime.getRuntime().freeMemory());
/* This will return Long.MAX_VALUE if there is no preset limit */
long maxMemory = Runtime.getRuntime().maxMemory();
/* Maximum amount of memory the JVM will attempt to use */
System.out.println("Maximum memory (bytes): " +
(maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));
/* Total memory currently available to the JVM */
System.out.println("Total memory available to JVM (bytes): " +
Runtime.getRuntime().totalMemory());
/* Get a list of all filesystem roots on this system */
File[] roots = File.listRoots();
/* For each filesystem root, print some info */
for (File root : roots) {
System.out.println("File system root: " + root.getAbsolutePath());
System.out.println("Total space (bytes): " + root.getTotalSpace());
System.out.println("Free space (bytes): " + root.getFreeSpace());
System.out.println("Usable space (bytes): " + root.getUsableSpace());
}
}
}
Le java.lang.le paquet management vous donne beaucoup plus d'informations que Runtime - par exemple, il vous donnera de la mémoire de tas (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()
) séparée de la mémoire non-tas (ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()
).
Vous pouvez également obtenir l'utilisation du processeur de processus (sans écrire votre propre code JNI), mais vous devez convertir le java.lang.management.OperatingSystemMXBean
en com.sun.management.OperatingSystemMXBean
. Cela fonctionne sur Windows et Linux, Je ne l'ai pas testé ailleurs.
Par exemple ... appelez la méthode get getcpuusage() plus fréquemment pour obtenir plus de précision lecture.
public class PerformanceMonitor {
private int availableProcessors = getOperatingSystemMXBean().getAvailableProcessors();
private long lastSystemTime = 0;
private long lastProcessCpuTime = 0;
public synchronized double getCpuUsage()
{
if ( lastSystemTime == 0 )
{
baselineCounters();
return;
}
long systemTime = System.nanoTime();
long processCpuTime = 0;
if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
{
processCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
}
double cpuUsage = (double) ( processCpuTime - lastProcessCpuTime ) / ( systemTime - lastSystemTime );
lastSystemTime = systemTime;
lastProcessCpuTime = processCpuTime;
return cpuUsage / availableProcessors;
}
private void baselineCounters()
{
lastSystemTime = System.nanoTime();
if ( getOperatingSystemMXBean() instanceof OperatingSystemMXBean )
{
lastProcessCpuTime = ( (OperatingSystemMXBean) getOperatingSystemMXBean() ).getProcessCpuTime();
}
}
}
Je pense que la meilleure méthode est d'implémenter l'API SIGAR par Hyperic . Il fonctionne pour la plupart des principaux systèmes d'exploitation ( sacrément près de tout ce qui est moderne ) et est très facile à travailler avec. Les développeurs sont très réactifs sur leur forum et leurs listes de diffusion. J'aime aussi que c'est GPL2 Apache sous licence . Ils fournissent une tonne d'exemples en Java aussi!
SIGAR == outil D'information, de collecte et de Reporting du système.
Il y a un projet Java qui utilise JNA (donc pas de bibliothèques natives à installer) et est en développement actif. Il prend actuellement en charge Linux, OSX, Windows, Solaris et FreeBSD et fournit des informations sur la RAM, le processeur, la batterie et le système de fichiers.
Vous pouvez obtenir des informations au niveau du système en utilisant System.getenv()
, en passant le nom de la variable d'environnement pertinente en tant que paramètre. Par exemple, sous Windows:
System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")
Pour les autres systèmes d'exploitation, la Présence / absence et les noms des variables d'environnement pertinentes diffèrent.
Pour windows, je suis allé de cette façon.
com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
long physicalMemorySize = os.getTotalPhysicalMemorySize();
long freePhysicalMemory = os.getFreePhysicalMemorySize();
long freeSwapSize = os.getFreeSwapSpaceSize();
long commitedVirtualMemorySize = os.getCommittedVirtualMemorySize();
Jetez un oeil aux API disponibles dans le java.lang.gestion paquet. Par exemple:
OperatingSystemMXBean.getSystemLoadAverage()
ThreadMXBean.getCurrentThreadCpuTime()
ThreadMXBean.getCurrentThreadUserTime()
Il y a beaucoup d'autres choses utiles là-dedans aussi.
Ajouter une dépendance OSHI via maven:
<dependency>
<groupId>com.github.dblock</groupId>
<artifactId>oshi-core</artifactId>
<version>2.2</version>
</dependency>
Obtenir une capacité de la batterie en pourcentage:
SystemInfo si = new SystemInfo();
HardwareAbstractionLayer hal = si.getHardware();
for (PowerSource pSource : hal.getPowerSources()) {
System.out.println(String.format("%n %s @ %.1f%%", pSource.getName(), pSource.getRemainingCapacity() * 100d));
}
Habituellement, pour obtenir des informations de bas niveau sur le système d'exploitation, vous pouvez appeler des commandes spécifiques au système d'exploitation qui vous donnent les informations que vous voulez avec Runtime.exec() ou lire des fichiers tels que / proc/ * sous Linux.
L'utilisation du processeur n'est pas simple-java.lang.gestion via com.soleil.gestion.OperatingSystemMXBean.getProcessCpuTime se rapproche (voir L'excellent extrait de code de Patrick ci-dessus) mais notez qu'il ne donne accès qu'au temps passé par le processeur dans votre processus. il ne vous dira pas sur le temps CPU passé dans d'autres processus, ou même le temps CPU passé à faire des activités du système liées à votre processus.
Par exemple, j'ai un processus java gourmand en réseau - c'est la seule chose en cours d'exécution et le CPU est à 99% , mais seulement 55% de cela est rapporté comme "processeur CPU".
Ne me lancez même pas sur "load average" car il est presque inutile, en dépit d'être le seul élément lié au processeur sur le bean MX. si seulement sun dans leur sagesse occasionnelle exposait quelque chose comme "getTotalCpuTime"...
Pour la surveillance sérieuse du processeur SIGAR mentionné par Matt semble le meilleur pari.
, Il est encore en développement, mais vous pouvez déjà utiliser jHardware
C'est une bibliothèque simple qui supprime les données système en utilisant Java. Il fonctionne à la fois sous Linux et Windows.
ProcessorInfo info = HardwareInfo.getProcessorInfo();
//Get named info
System.out.println("Cache size: " + info.getCacheSize());
System.out.println("Family: " + info.getFamily());
System.out.println("Speed (Mhz): " + info.getMhz());
//[...]
Si vous utilisez Jrockit VM, voici une autre façon d'obtenir L'utilisation du processeur VM. Runtime bean peut également vous donner une charge CPU par processeur. Je l'ai utilisé uniquement sur Red Hat Linux pour observer les performances de Tomcat. Vous devez activer JMX remote dans catalina.sh pour que cela fonctionne.
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://my.tomcat.host:8080/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
MBeanServerConnection conn = jmxc.getMBeanServerConnection();
ObjectName name = new ObjectName("oracle.jrockit.management:type=Runtime");
Double jvmCpuLoad =(Double)conn.getAttribute(name, "VMGeneratedCPULoad");
Sur Windows
, vous pouvez exécuter la commande systeminfo
et récupérer sa sortie par exemple avec le code suivant:
private static class WindowsSystemInformation
{
static String get() throws IOException
{
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("systeminfo");
BufferedReader systemInformationReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = systemInformationReader.readLine()) != null)
{
stringBuilder.append(line);
stringBuilder.append(System.lineSeparator());
}
return stringBuilder.toString().trim();
}
}