Domanda

Attualmente sto creando un'app Java che potrebbe essere eseguita su molte piattaforme diverse, ma principalmente varianti di Solaris, Linux e Windows.

Qualcuno è riuscito a estrarre con successo informazioni quali lo spazio su disco attualmente utilizzato, l'utilizzo della CPU e la memoria utilizzata nel sistema operativo sottostante?Che dire di ciò che consuma l'app Java stessa?

Preferibilmente mi piacerebbe ottenere queste informazioni senza utilizzare JNI.

È stato utile?

Soluzione

È possibile ottenere alcune informazioni sulla memoria limitata dalla classe Runtime.In realtà non è esattamente quello che stai cercando, ma ho pensato di fornirlo per completezza.Ecco un piccolo esempio.Modificare:Puoi anche ottenere informazioni sull'utilizzo del disco dalla classe java.io.File.Le informazioni sull'utilizzo dello spazio su disco richiedono Java 1.6 o versione successiva.

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

Altri suggerimenti

IL java.lang.management pacchetto ti fornisce molte più informazioni rispetto a Runtime, ad esempio ti fornirà memoria heap (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) separato dalla memoria non heap (ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

Puoi anche ottenere l'utilizzo della CPU del processo (senza scrivere il tuo codice JNI), ma devi trasmettere il file java.lang.management.OperatingSystemMXBean ad a com.sun.management.OperatingSystemMXBean.Funziona su Windows e Linux, non l'ho testato altrove.

Per esempio ...chiamare il metodo get getCpuUsage() più frequentemente per ottenere letture più accurate.

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

Penso che il metodo migliore disponibile sia implementare il file API SIGAR di Hyperic.Funziona con la maggior parte dei principali sistemi operativi (dannatamente quasi qualsiasi cosa moderna) ed è molto facile da usare.Gli sviluppatori sono molto reattivi sul loro forum e sulle mailing list.Mi piace anche così GPL2 Licenza Apache.Forniscono anche moltissimi esempi in Java!

SIGAR == Strumento per la raccolta e la creazione di report di informazioni di sistema.

Esiste un progetto Java che utilizza JNA (quindi nessuna libreria nativa da installare) ed è in fase di sviluppo attivo.Attualmente supporta Linux, OSX, Windows, Solaris e FreeBSD e fornisce informazioni su RAM, CPU, batteria e file system.

È possibile ottenere alcune informazioni a livello di sistema utilizzando System.getenv(), passando il nome della variabile di ambiente pertinente come parametro.Ad esempio, su Windows:

System.getenv("PROCESSOR_IDENTIFIER")
System.getenv("PROCESSOR_ARCHITECTURE")
System.getenv("PROCESSOR_ARCHITEW6432")
System.getenv("NUMBER_OF_PROCESSORS")

Per altri sistemi operativi la presenza/assenza e i nomi delle variabili d'ambiente rilevanti saranno diversi.

Per Windows ho seguito questa strada.

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

Ecco il collegamento con dettagli.

Aggiungi la dipendenza OSHI tramite Maven:

<dependency>
    <groupId>com.github.dblock</groupId>
    <artifactId>oshi-core</artifactId>
    <version>2.2</version>
</dependency>

Ottieni la capacità della batteria rimasta in percentuale:

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

Dai un'occhiata alle API disponibili in java.lang.management pacchetto.Per esempio:

  • OperatingSystemMXBean.getSystemLoadAverage()
  • ThreadMXBean.getCurrentThreadCpuTime()
  • ThreadMXBean.getCurrentThreadUserTime()

Ci sono anche un sacco di altre cose utili lì dentro.

Di solito, per ottenere informazioni sul sistema operativo di basso livello è possibile chiamare comandi specifici del sistema operativo che forniscono le informazioni desiderate con Runtime.exec() o leggere file come /proc/* in Linux.

L'utilizzo della CPU non è semplice: java.lang.management tramite com.sun.management.OperatingSystemMXBean.getProcessCpuTime si avvicina (vedi l'eccellente snippet di codice di Patrick sopra) ma tieni presente che dà accesso solo al tempo impiegato dalla CPU nel processo.non ti dirà del tempo della CPU impiegato in altri processi, o anche del tempo della CPU impiegato per svolgere attività di sistema relative al tuo processo.

ad esempio ho un processo Java ad uso intensivo della rete: è l'unica cosa in esecuzione e la CPU è al 99% ma solo il 55% viene segnalato come "CPU del processore".

non farmi nemmeno iniziare con il "carico medio" poiché è quasi inutile, nonostante sia l'unico elemento relativo alla CPU sul bean MX.se solo il sole nella loro saggezza occasionale rivelasse qualcosa come "getTotalCpuTime"...

per un serio monitoraggio della CPU SIGAR menzionato da Matt sembra la soluzione migliore.

È ancora in fase di sviluppo ma è già possibile utilizzarlo jHardware

È una semplice libreria che elimina i dati di sistema utilizzando Java.Funziona sia su Linux che su 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());
//[...]

Se stai utilizzando Jrockit VM, ecco un altro modo per ottenere l'utilizzo della CPU della VM.Il bean runtime può anche fornire il carico della CPU per processore.L'ho usato solo su Red Hat Linux per osservare le prestazioni di Tomcat.È necessario abilitare il telecomando JMX in catalina.sh affinché funzioni.

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

SU Windows, puoi eseguire il file systeminfo comando e recupera il suo output, ad esempio con il seguente codice:

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

Un modo semplice che può essere utilizzato per ottenere informazioni sul livello del sistema operativo e che ho testato sul mio Mac che funziona bene:

 OperatingSystemMXBean osBean =
        (OperatingSystemMXBean)ManagementFactory.getOperatingSystemMXBean();
    return osBean.getProcessCpuLoad();

Puoi trovare molte metriche rilevanti del sistema operativo Qui

Ehi, puoi farlo con l'integrazione Java/com.Accedendo alle funzionalità WMI potrai ottenere tutte le informazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top