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.

219
demandé sur Hrqls 2008-08-25 05:49:55

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());
    }
  }
}
192
répondu William Brendel 2014-01-10 19:34:10

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();
        }
    }
}
92
répondu Patrick Wilkes 2011-05-17 02:59:50

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.

40
répondu Matt Cummings 2017-09-27 19:24:20

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.

20
répondu dB. 2016-09-01 15:56:47

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.

10
répondu Alexandr 2012-08-16 15:39:38

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();

Voici le lien avec les détails.

7
répondu Yan Khonski 2017-01-13 11:50:11

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.

6
répondu staffan 2008-08-26 07:09:20

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));
}
6
répondu Oleksii Kyslytsyn 2016-04-10 18:01:01

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.

5
répondu Peter Lawrey 2009-03-24 19:43:26

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.

5
répondu Partly Cloudy 2009-06-02 02:01:18

, 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());
//[...]
4
répondu profesor_falken 2016-09-03 17:54:36

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");
2
répondu petro 2011-11-10 07:55:07

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();
    }
}
2
répondu BullyWiiPlaza 2016-10-27 09:56:54

Hey, vous pouvez le faire avec l'intégration java/com. En accédant aux fonctionnalités WMI, vous pouvez obtenir toutes les informations.

1
répondu 2009-03-24 12:32:46