Como faço para verificar o uso de CPU e memória em Java?

Respostas:

73

Se você estiver procurando especificamente por memória na JVM:

Runtime runtime = Runtime.getRuntime();

NumberFormat format = NumberFormat.getInstance();

StringBuilder sb = new StringBuilder();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();

sb.append("free memory: " + format.format(freeMemory / 1024) + "<br/>");
sb.append("allocated memory: " + format.format(allocatedMemory / 1024) + "<br/>");
sb.append("max memory: " + format.format(maxMemory / 1024) + "<br/>");
sb.append("total free memory: " + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024) + "<br/>");

No entanto, estes devem ser considerados apenas como uma estimativa ...

Jeremy
fonte
Então, se eu estiver executando no Eclipse, isso dependerá das minhas configurações do Eclipse?
Café
4
Observe que esta não é a memória usada real - esta é a 'memória alocada' que significa o heap que o java alocou, então se você tiver -Xms90g e seu aplicativo for muito leve, você ainda obterá memória alocada como algo maior que 90g . Veja a resposta excluída "desconhecido (yahoo)" abaixo (que pode ser diferente à primeira vista)
0fnt
Só por curiosidade, por que isso deveria ser apenas uma estimativa?
ComputerScientist
@ComputerScientist Como o Grátis é na verdade o que é grátis (pós GC), ele não mostra objetos esperando por GC. Para obter muito mais precisão, execute 2 coletas de lixo antes desta resposta. Se você tentar com e sem GC, você encontrará os valores pós-GC muito consistentes, mas o pré-GC geralmente será pelo menos o dobro desses valores.
Bill K
@sbeliakov Você pode usar JavaSysmon ( github.com/jezhumble/javasysmon ), embora eu recomendo que você abra uma nova pergunta e eu responderei. A biblioteca no GitHub tem um bug e reconhece 32 bits como 64 bits, mas descobri uma solução alternativa para misturar diferentes jars [ github.com/goxr3plus/XR3Player/blob/master/resources/libs/… ].
GOXR3PLUS
20
package mkd.Utils;

import java.io.File;
import java.text.NumberFormat;

public class systemInfo {

    private Runtime runtime = Runtime.getRuntime();

    public String Info() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.OsInfo());
        sb.append(this.MemInfo());
        sb.append(this.DiskInfo());
        return sb.toString();
    }

    public String OSname() {
        return System.getProperty("os.name");
    }

    public String OSversion() {
        return System.getProperty("os.version");
    }

    public String OsArch() {
        return System.getProperty("os.arch");
    }

    public long totalMem() {
        return Runtime.getRuntime().totalMemory();
    }

    public long usedMem() {
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    }

    public String MemInfo() {
        NumberFormat format = NumberFormat.getInstance();
        StringBuilder sb = new StringBuilder();
        long maxMemory = runtime.maxMemory();
        long allocatedMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        sb.append("Free memory: ");
        sb.append(format.format(freeMemory / 1024));
        sb.append("<br/>");
        sb.append("Allocated memory: ");
        sb.append(format.format(allocatedMemory / 1024));
        sb.append("<br/>");
        sb.append("Max memory: ");
        sb.append(format.format(maxMemory / 1024));
        sb.append("<br/>");
        sb.append("Total free memory: ");
        sb.append(format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024));
        sb.append("<br/>");
        return sb.toString();

    }

    public String OsInfo() {
        StringBuilder sb = new StringBuilder();
        sb.append("OS: ");
        sb.append(this.OSname());
        sb.append("<br/>");
        sb.append("Version: ");
        sb.append(this.OSversion());
        sb.append("<br/>");
        sb.append(": ");
        sb.append(this.OsArch());
        sb.append("<br/>");
        sb.append("Available processors (cores): ");
        sb.append(runtime.availableProcessors());
        sb.append("<br/>");
        return sb.toString();
    }

    public String DiskInfo() {
        /* Get a list of all filesystem roots on this system */
        File[] roots = File.listRoots();
        StringBuilder sb = new StringBuilder();

        /* For each filesystem root, print some info */
        for (File root : roots) {
            sb.append("File system root: ");
            sb.append(root.getAbsolutePath());
            sb.append("<br/>");
            sb.append("Total space (bytes): ");
            sb.append(root.getTotalSpace());
            sb.append("<br/>");
            sb.append("Free space (bytes): ");
            sb.append(root.getFreeSpace());
            sb.append("<br/>");
            sb.append("Usable space (bytes): ");
            sb.append(root.getUsableSpace());
            sb.append("<br/>");
        }
        return sb.toString();
    }
}
Dave
fonte
meu entendimento de que o tópico começou era perguntando sobre a quantidade de memória disponível no sistema operacional. freeMemoryaqui retorna a quantidade de memória disponível na JVM que é muito diferente
Tagar
Não é estranho que sua classe SystemInfo não comece com Capital e seus métodos Info (), OSname (), MemInfo () sim?
Drswaki69,
18

Se você estiver usando o Sun JVM e estiver interessado no uso da memória interna do aplicativo (quanto da memória alocada seu aplicativo está usando), prefiro ativar o registro de coleta de lixo integrado do JVM. Você simplesmente adiciona -verbose: gc ao comando de inicialização.

Da documentação da Sun:

O argumento da linha de comando -verbose: gc imprime informações em cada coleção. Observe que o formato da saída -verbose: gc está sujeito a alterações entre os releases da plataforma J2SE. Por exemplo, aqui está a saída de um grande aplicativo de servidor:

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

Aqui, vemos duas coleções menores e uma principal. Os números antes e depois da seta

325407K->83000K (in the first line)

indicam o tamanho combinado dos objetos ativos antes e depois da coleta de lixo, respectivamente. Após coleções secundárias, a contagem inclui objetos que não estão necessariamente vivos, mas não podem ser recuperados, seja porque estão diretamente vivos, ou porque estão dentro ou são referenciados pela geração titular. O número entre parênteses

(776768K) (in the first line)

é o espaço total disponível, sem contar o espaço na geração permanente, que é a pilha total menos um dos espaços sobreviventes. A coleção menor demorou cerca de um quarto de segundo.

0.2300771 secs (in the first line)

Para obter mais informações, consulte: http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html

Steve Blackwell
fonte
17

A partir daqui

    OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
    int availableProcessors = operatingSystemMXBean.getAvailableProcessors();
    long prevUpTime = runtimeMXBean.getUptime();
    long prevProcessCpuTime = operatingSystemMXBean.getProcessCpuTime();
    double cpuUsage;
    try
    {
        Thread.sleep(500);
    }
    catch (Exception ignored) { }

    operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    long upTime = runtimeMXBean.getUptime();
    long processCpuTime = operatingSystemMXBean.getProcessCpuTime();
    long elapsedCpu = processCpuTime - prevProcessCpuTime;
    long elapsedTime = upTime - prevUpTime;

    cpuUsage = Math.min(99F, elapsedCpu / (elapsedTime * 10000F * availableProcessors));
    System.out.println("Java CPU: " + cpuUsage);
danieln
fonte
1
E sobre a memória?
Daniel De León
2
Listar <MemoryPoolMXBean> memoryPools = novo ArrayList <MemoryPoolMXBean> (ManagementFactory.getMemoryPoolMXBeans ()); long usedHeapMemoryAfterLastGC = 0; for (MemoryPoolMXBean memoryPool: memoryPools) {if (memoryPool.getType (). equals (MemoryType.HEAP)) {MemoryUsage poolCollectionMemoryUsage = memoryPool.getCollectionUsage (); usedHeapMemoryAfterLastGC + = poolCollectionMemoryUsage.getUsed (); }}
danieln 01 de
1
Obrigado pela única resposta que mostra a recuperação do uso da CPU.
Matthieu de
1
Qual é a diferença entre fazer isso e simplesmente fazer operatingSystemMXBean.getProcessCpuLoad();? De acordo com a documentação do Oracle, este método retorna "Retorna o" uso recente da CPU "para o processo da Java Virtual Machine." No entanto, vejo uma diferença numérica relativamente grande entre seu método e este método.
Ishnark
1
@RobHall Existem duas OperatingSystemMXBeanclasses. Uma é a interface fornecida em java.lang. Mas também há outra versão, que estende esta em com.sun.management. Esse é o método que eu estava me referindoOperatingSystemMXBean
Ishnark
9

JMX, o MXBeans (ThreadMXBean, etc) fornecido fornecerá os usos de memória e CPU.

OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
operatingSystemMXBean.getSystemCpuLoad();
Javamann
fonte
8

Para uso de memória, o seguinte funcionará,

long total = Runtime.getRuntime().totalMemory();
long used  = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Para o uso da CPU, você precisará usar um aplicativo externo para medi-lo.

Rich Adams
fonte
5

Desde o Java 1.5, o JDK vem com uma nova ferramenta: JConsole que pode mostrar o uso de CPU e memória de qualquer JVM 1.5 ou posterior. Pode fazer gráficos desses parâmetros, exportar para CSV, mostrar o número de classes carregadas, o número de instâncias, deadlocks, threads etc ...

Telcontar
fonte
4

Se você usar a solução runtime / totalMemory que foi postada em muitas respostas aqui (eu fiz muito isso), certifique-se de forçar duas coletas de lixo primeiro se quiser resultados razoavelmente precisos / consistentes.

Para eficiência, o Java geralmente permite que o lixo encha toda a memória antes de forçar um GC, e mesmo assim não é geralmente um GC completo, então seus resultados para runtime.freeMemory () sempre estarão em algum lugar entre a quantidade "real" de memória livre e 0 .

O primeiro GC não consegue tudo, ele consegue a maior parte.

A melhora é que se você apenas fizer a chamada freeMemory (), obterá um número que é absolutamente inútil e varia muito, mas se você fizer 2 gc's primeiro, é um medidor muito confiável. Também torna a rotina MUITO mais lenta (segundos, possivelmente).

Bill K
fonte
3

O objeto Runtime do Java pode relatar o uso de memória da JVM. Para o consumo da CPU você terá que usar um utilitário externo, como o top Unix ou o Gerenciador de Processos do Windows.

sombra da Lua
fonte
2

Aqui está um código simples para calcular o uso de memória atual em megabytes:

double currentMemory = ( (double)((double)(Runtime.getRuntime().totalMemory()/1024)/1024))- ((double)((double)(Runtime.getRuntime().freeMemory()/1024)/1024));
Phil
fonte
2

Eu também adicionaria a seguinte maneira de rastrear a carga da CPU:

import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;

double getCpuLoad() {
    OperatingSystemMXBean osBean =
        (com.sun.management.OperatingSystemMXBean) ManagementFactory.
        getPlatformMXBeans(OperatingSystemMXBean.class);
    return osBean.getProcessCpuLoad();
}

Você pode ler mais aqui

Sbeliakov
fonte
1

JConsole é uma maneira fácil de monitorar um aplicativo Java em execução ou você pode usar um Profiler para obter informações mais detalhadas sobre seu aplicativo. Gosto de usar o Perfilador do NetBeans para isso.

blahspam
fonte
1

Se você estiver usando o Tomcat, verifique Psi Probe , que permite monitorar o consumo de memória interna e externa, bem como uma série de outras áreas.

Tim Howland
fonte
0

Para Eclipse, você pode usar TPTP (plataforma de ferramentas de teste e desempenho) para analisar o uso de memória e etc. mais informações

Fuangwith S.
fonte