obter informações do sistema no nível do sistema operacional

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

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

De preferência, gostaria de obter essa informação sem usar o JNI.

Você pode obter algumas informações de memory limitadas da class Runtime. Realmente não é exatamente o que você está procurando, mas eu pensei em fornecer isso por uma questão de completude. Aqui está um pequeno exemplo. Edit: Você também pode obter informações de uso de disco da class java.io.File. O material de uso do espaço em disco requer o Java 1.6 ou superior.

 public class Main { public static void main(String[] args) { /* Total number of processors or colors available to the JVM */ System.out.println("Available processors (colors): " + 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()); } } } 

O pacote java.lang.management oferece muito mais informações do que o Runtime – por exemplo, ele fornecerá a memory de heap ( ManagementFactory.getMemoryMXBean().getHeapMemoryUsage() ) separada da memory 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 é necessário converter o java.lang.management.OperatingSystemMXBean em um com.sun.management.OperatingSystemMXBean . Isso funciona no Windows e Linux, eu não testei em outro lugar.

Por exemplo … chame o método get getPuUsage () com mais freqüê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(); } } } 

Eu acho que o melhor método lá fora é implementar a API SIGAR da Hyperic . Ele funciona para a maioria dos principais sistemas operacionais (quase qualquer coisa moderna) e é muito fácil de se trabalhar. O (s) desenvolvedor (es) são muito responsivos em seus fóruns e listas de discussão. Eu também gosto que é GPL2 Apache licenciado . Eles fornecem uma tonelada de exemplos em Java também!

SIGAR == Informações do sistema, ferramenta de coleta e geração de relatórios.

Há um projeto Java que usa o JNA (portanto, não há bibliotecas nativas para instalar) e está em desenvolvimento ativo. Atualmente ele 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 um 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 variables ​​de ambiente relevantes serão diferentes.

Para o windows eu fui assim.

  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.

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

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

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

Adicionar dependência OSHI via maven:

  com.github.dblock oshi-core 2.2  

Obtenha uma capacidade da bateria restante 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)); } 

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

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

por exemplo, eu tenho um processo java intensivo em rede – é a única coisa que roda e a CPU está em 99%, mas apenas 55% disso é reportado como “CPU do processador”.

nem sequer me inicie em “load average”, pois é quase inútil, apesar de ser o único item relacionado a CPU no bean MX. se apenas sol em sua sabedoria ocasional exposta algo como “getTotalCpuTime” …

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

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

É uma biblioteca simples que recolhe dados do sistema usando Java. Funciona tanto no Linux quanto no 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 o VM Jrockit, então aqui está uma outra maneira de obter o uso da CPU da VM. O bean de tempo de execução também pode fornecer a carga da CPU por processador. Eu usei isso apenas no Red Hat Linux para observar o desempenho do Tomcat. Você precisa habilitar o JMX remote 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"); 

No Windows , você pode executar o comando systeminfo e recuperar 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(); } } 

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