Pergunta

Atualmente estou construindo um aplicativo Java que pode acabar sendo executado em muitas plataformas diferentes, mas principalmente em variantes do Solaris, Linux e Windows.

Alguém conseguiu extrair com êxito informações como o espaço em disco atual usado, a utilização da CPU e a memória usada no sistema operacional subjacente?E quanto ao que o próprio aplicativo Java está consumindo?

De preferência, gostaria de obter essas informações sem usar JNI.

Foi útil?

Solução

Você pode obter algumas informações de memória limitada na classe Runtime.Na verdade, não é exatamente o que você está procurando, mas pensei em fornecê-lo por uma questão de integridade.Aqui está um pequeno exemplo.Editar:Você também pode obter informações de uso do disco na classe java.io.File.O uso do espaço em disco requer Java 1.6 ou superior.

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

Outras dicas

O java.lang.management O pacote fornece muito mais informações do que o Runtime - por exemplo, fornece memória heap (ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()) separado da memória não heap (ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()).

Você também pode obter o uso da CPU do processo (sem escrever seu próprio código JNI), mas precisa converter o java.lang.management.OperatingSystemMXBean para um com.sun.management.OperatingSystemMXBean.Isso funciona no Windows e Linux, não testei em outro lugar.

Por exemplo ...chame o método getCpuUsage() com mais frequência para obter leituras mais precisas.

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

Acho que o melhor método que existe é implementar o API SIGAR da Hyperic.Ele funciona para a maioria dos principais sistemas operacionais (quase qualquer coisa moderna) e é muito fácil de trabalhar.O(s) desenvolvedor(es) são muito receptivos em seus fóruns e listas de discussão.Eu também gosto que seja GPL2 Licença Apache.Eles também fornecem muitos exemplos em Java!

SIGAR == Ferramenta de informações, coleta e relatórios do sistema.

Há um projeto Java que usa JNA (portanto, não há bibliotecas nativas para instalar) e está em desenvolvimento ativo.Atualmente suporta Linux, OSX, Windows, Solaris e FreeBSD e fornece informações de RAM, CPU, bateria e sistema de arquivos.

Você pode obter algumas informações no nível do sistema usando System.getenv(), passando o nome da variável de ambiente relevante como parâmetro.Por exemplo, no Windows:

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

Para outros sistemas operacionais, a presença/ausência e os nomes das variáveis ​​de ambiente relevantes serão diferentes.

Para janelas eu fui por aqui.

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

Aqui está o link com detalhes.

Adicione dependência OSHI via maven:

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

Obtenha a capacidade restante da bateria em porcentagem:

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

Dê uma olhada nas APIs disponíveis no java.lang.management pacote.Por exemplo:

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

Há muitas outras coisas úteis lá também.

Normalmente, para obter informações de baixo nível do sistema operacional, você pode chamar comandos específicos do sistema operacional que fornecem as informações desejadas com Runtime.exec() ou ler arquivos como /proc/* no Linux.

O uso da CPU não é direto - java.lang.management via com.sun.management.OperatingSystemMXBean.getProcessCpuTime chega perto (veja o excelente trecho de código de Patrick acima), mas observe que ele só dá acesso ao tempo que a CPU gastou em seu processo.ele não informa sobre o tempo de CPU gasto em outros processos, ou mesmo o tempo de CPU gasto em atividades do sistema relacionadas ao seu processo.

por exemplo, eu tenho um processo Java com uso intensivo de rede - é a única coisa em execução e a CPU está em 99%, mas apenas 55% disso é relatado como "CPU do processador".

nem me fale sobre "carga média", pois é quase inútil, apesar de ser o único item relacionado à CPU no bean MX.se ao menos o sol, em sua sabedoria ocasional, expusesse algo como "getTotalCpuTime" ...

para monitoramento sério da CPU, o SIGAR mencionado por Matt parece a melhor aposta.

Ainda está em desenvolvimento, mas você já pode usar jHardware

É uma biblioteca simples que elimina dados do sistema usando Java.Funciona tanto em Linux quanto em 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 você estiver usando Jrockit VM, aqui está outra maneira de obter o uso da CPU da VM.O runtime bean também pode fornecer carga de CPU por processador.Usei isso apenas no Red Hat Linux para observar o desempenho do Tomcat.Você deve habilitar o JMX remoto em catalina.sh para que isso funcione.

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

Sobre Windows, você pode executar o systeminfo comando e recupera sua saída, por exemplo, com o seguinte código:

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

Uma maneira simples que pode ser usada para obter informações sobre o nível do sistema operacional e testei no meu Mac que funciona bem:

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

Você pode encontrar muitas métricas relevantes do sistema operacional aqui

Ei, você pode fazer isso com integração java/com.Acessando os recursos do WMI você pode obter todas as informações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top