O que são Runtime.getRuntime (). TotalMemory () e freeMemory ()?


Respostas:


195

De acordo com a API

totalMemory()

Retorna a quantidade total de memória na máquina virtual Java. O valor retornado por esse método pode variar com o tempo, dependendo do ambiente do host. Observe que a quantidade de memória necessária para armazenar um objeto de qualquer tipo pode ser dependente da implementação.

maxMemory()

Retorna a quantidade máxima de memória que a máquina virtual Java tentará usar. Se não houver limite inerente, o valor Long.MAX_VALUE será retornado.

freeMemory()

Retorna a quantidade de memória livre na Java Virtual Machine. Chamar o método gc pode resultar no aumento do valor retornado pelo freeMemory.

Em referência à sua pergunta, maxMemory()retorna o -Xmxvalor.

Você pode estar se perguntando por que existe um totalMemory () AND um maxMemory () . A resposta é que a JVM aloca memória lentamente. Digamos que você inicie seu processo Java como tal:

java -Xms64m -Xmx1024m Foo

Seu processo começa com 64 MB de memória e, se e quando precisar de mais (até 1024 m), ele alocará memória. totalMemory()corresponde à quantidade de memória atualmente disponível para a JVM for Foo. Se a JVM precisar de mais memória, ela a alocará preguiçosamente até a memória máxima. Se você executar com -Xms1024m -Xmx1024m, o valor obtido totalMemory()e maxMemory()será igual.

Além disso, se você deseja calcular com precisão a quantidade de memória usada , faça-o com o seguinte cálculo:

final long usedMem = totalMemory() - freeMemory();

O -Xmxvalor parece afetar diretamente o maxMemory()valor inicial, no entanto, vi o maxMemory()aumento relatado em uma pequena quantidade, talvez ~ 1%, enquanto o programa está sendo executado.
H2ONaCl 17/01

2
Como isso é diferente Debug.getNativeHeapFreeSize()?
IgorGanapolsky

@ H2ONaCl sim, pode mudar um pouco, porque as JVM UseAdaptiveSizePolicyestão ativadas por padrão. E BTW: maxMemory()= Xmx- tamanho de um único espaço de sobrevivente. Por quê? Porque, ao mesmo tempo, apenas um espaço de sobrevivente pode ser usado.
G. Demecki 17/03/19

236

Os nomes e valores são confusos. Se você estiver procurando a memória livre total , precisará calcular esse valor sozinho. Não é o que você recebe freeMemory();.

Consulte o seguinte guia:

Memória total designada , será igual ao valor -Xmx configurado :

Runtime.getRuntime (). MaxMemory ();

Memória livre alocada atual , é o espaço alocado atual pronto para novos objetos. Cuidado, essa não é a memória total disponível livre :

Runtime.getRuntime (). FreeMemory ();

Memória total alocada , é o espaço total alocado reservado para o processo java:

Runtime.getRuntime (). TotalMemory ();

A memória usada deve ser calculada:

usedMemory = Runtime.getRuntime (). totalMemory () - Runtime.getRuntime (). freeMemory ();

A memória livre total deve ser calculada:

freeMemory = Runtime.getRuntime (). maxMemory () - usedMemory;

Uma imagem pode ajudar a esclarecer:

memória runtime java


1
Isso é diferente Debug.getMemoryInfo()?
IgorGanapolsky

1
Nota: A memória usada pode não conter mais objetos referenciados que serão varridos pelo próximo GC.
102616 Gab Gabo

@cheneym, a memória livre e não localizada será ocupada, pois as instruções do código de bytes java serão processadas pelo processador somente se "Xmx - Usedmemory" estiver disponível na máquina. Xmx é como a capacidade máxima de ballon, que pode encher com o ar que sai do ar avlbl na própria máquina; assim que receber ar, ele será preenchido e explodirá uma vez que exceder o limite de Xmx. Mas a memória livre total não informa a memória avbl real na máquina para a JVM, mas apenas o nmbr. Existe alguma maneira de descobrir a memória avlbl real na máquina para que eu possa saber se a memória rqd é avlbl ou não para a renovação da JVM processo ?
Maria

12

Para entender melhor, execute o seguinte programa (em jdk1.7.x):

$ java -Xms1025k -Xmx1025k -XshowSettings:vm  MemoryTest

Isso imprimirá as opções da jvm e a memória usada , livre , total e máxima disponível na jvm.

public class MemoryTest {    
    public static void main(String args[]) {
                System.out.println("Used Memory   :  " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) + " bytes");
                System.out.println("Free Memory   : " + Runtime.getRuntime().freeMemory() + " bytes");
                System.out.println("Total Memory  : " + Runtime.getRuntime().totalMemory() + " bytes");
                System.out.println("Max Memory    : " + Runtime.getRuntime().maxMemory() + " bytes");            
        }
}

8

Versão codificada de todas as outras respostas (no momento da redação):

import java.io.*;

/**
 * This class is based on <a href="http://stackoverflow.com/users/2478930/cheneym">cheneym</a>'s
 * <a href="http://stackoverflow.com/a/18375641/253468">awesome interpretation</a>
 * of the Java {@link Runtime}'s memory query methods, which reflects intuitive thinking.
 * Also includes comments and observations from others on the same question, and my own experience.
 * <p>
 * <img src="https://i.stack.imgur.com/GjuwM.png" alt="Runtime's memory interpretation">
 * <p>
 * <b>JVM memory management crash course</b>:
 * Java virtual machine process' heap size is bounded by the maximum memory allowed.
 * The startup and maximum size can be configured by JVM arguments.
 * JVMs don't allocate the maximum memory on startup as the program running may never require that.
 * This is to be a good player and not waste system resources unnecessarily.
 * Instead they allocate some memory and then grow when new allocations require it.
 * The garbage collector will be run at times to clean up unused objects to prevent this growing.
 * Many parameters of this management such as when to grow/shrink or which GC to use
 * can be tuned via advanced configuration parameters on JVM startup.
 *
 * @see <a href="http://stackoverflow.com/a/42567450/253468">
 *     What are Runtime.getRuntime().totalMemory() and freeMemory()?</a>
 * @see <a href="http://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf">
 *     Memory Management in the Sun Java HotSpot™ Virtual Machine</a>
 * @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html">
 *     Full VM options reference for Windows</a>
 * @see <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html">
 *     Full VM options reference for Linux, Mac OS X and Solaris</a>
 * @see <a href="http://www.oracle.com/technetwork/articles/java/vmoptions-jsp-140102.html">
 *     Java HotSpot VM Options quick reference</a>
 */
public class SystemMemory {

    // can be white-box mocked for testing
    private final Runtime runtime = Runtime.getRuntime();

    /**
     * <b>Total allocated memory</b>: space currently reserved for the JVM heap within the process.
     * <p>
     * <i>Caution</i>: this is not the total memory, the JVM may grow the heap for new allocations.
     */
    public long getAllocatedTotal() {
        return runtime.totalMemory();
    }

    /**
     * <b>Current allocated free memory</b>: space immediately ready for new objects.
     * <p>
     * <i>Caution</i>: this is not the total free available memory,
     * the JVM may grow the heap for new allocations.
     */
    public long getAllocatedFree() {
        return runtime.freeMemory();
    }

    /**
     * <b>Used memory</b>:
     * Java heap currently used by instantiated objects. 
     * <p>
     * <i>Caution</i>: May include no longer referenced objects, soft references, etc.
     * that will be swept away by the next garbage collection.
     */
    public long getUsed() {
        return getAllocatedTotal() - getAllocatedFree();
    }

    /**
     * <b>Maximum allocation</b>: the process' allocated memory will not grow any further.
     * <p>
     * <i>Caution</i>: This may change over time, do not cache it!
     * There are some JVMs / garbage collectors that can shrink the allocated process memory.
     * <p>
     * <i>Caution</i>: If this is true, the JVM will likely run GC more often.
     */
    public boolean isAtMaximumAllocation() {
        return getAllocatedTotal() == getTotal();
        // = return getUnallocated() == 0;
    }

    /**
     * <b>Unallocated memory</b>: amount of space the process' heap can grow.
     */
    public long getUnallocated() {
        return getTotal() - getAllocatedTotal();
    }

    /**
     * <b>Total designated memory</b>: this will equal the configured {@code -Xmx} value.
     * <p>
     * <i>Caution</i>: You can never allocate more memory than this, unless you use native code.
     */
    public long getTotal() {
        return runtime.maxMemory();
    }

    /**
     * <b>Total free memory</b>: memory available for new Objects,
     * even at the cost of growing the allocated memory of the process.
     */
    public long getFree() {
        return getTotal() - getUsed();
        // = return getAllocatedFree() + getUnallocated();
    }

    /**
     * <b>Unbounded memory</b>: there is no inherent limit on free memory.
     */
    public boolean isBounded() {
        return getTotal() != Long.MAX_VALUE;
    }

    /**
     * Dump of the current state for debugging or understanding the memory divisions.
     * <p>
     * <i>Caution</i>: Numbers may not match up exactly as state may change during the call.
     */
    public String getCurrentStats() {
        StringWriter backing = new StringWriter();
        PrintWriter out = new PrintWriter(backing, false);
        out.printf("Total: allocated %,d (%.1f%%) out of possible %,d; %s, %s %,d%n",
                getAllocatedTotal(),
                (float)getAllocatedTotal() / (float)getTotal() * 100,
                getTotal(),
                isBounded()? "bounded" : "unbounded",
                isAtMaximumAllocation()? "maxed out" : "can grow",
                getUnallocated()
        );
        out.printf("Used: %,d; %.1f%% of total (%,d); %.1f%% of allocated (%,d)%n",
                getUsed(),
                (float)getUsed() / (float)getTotal() * 100,
                getTotal(),
                (float)getUsed() / (float)getAllocatedTotal() * 100,
                getAllocatedTotal()
        );
        out.printf("Free: %,d (%.1f%%) out of %,d total; %,d (%.1f%%) out of %,d allocated%n",
                getFree(),
                (float)getFree() / (float)getTotal() * 100,
                getTotal(),
                getAllocatedFree(),
                (float)getAllocatedFree() / (float)getAllocatedTotal() * 100,
                getAllocatedTotal()
        );
        out.flush();
        return backing.toString();
    }

    public static void main(String... args) {
        SystemMemory memory = new SystemMemory();
        System.out.println(memory.getCurrentStats());
    }
}

7

Tempo de execução # totalMemory - a memória que a JVM alocou até o momento. Não é necessariamente o que está em uso ou o máximo.

Tempo de execução # maxMemory - a quantidade máxima de memória que a JVM foi configurada para usar. Quando seu processo atingir esse valor, a JVM não alocará mais e, em vez disso, o GC com muito mais frequência.

Tempo de execução # freeMemory - não tenho certeza se isso é medido a partir do máximo ou da parte do total que não é usada. Eu estou supondo que é uma medida da parte do total que não é utilizada.


5

O tamanho da pilha da JVM pode ser aumentado e reduzido pelo mecanismo de Coleta de Lixo. Mas não pode alocar acima do tamanho máximo da memória: Runtime.maxMemory. Este é o significado de memória máxima. Memória total significa o tamanho da pilha alocada. E memória livre significa o tamanho disponível na memória total.

exemplo) java -Xms20M -Xmn10M -Xmx50M ~~~. Isso significa que a jvm deve alocar o heap 20M na inicialização (ms). Nesse caso, a memória total é de 20M. a memória livre é do tamanho de 20M usado. Se for necessário mais heap, a JVM alocará mais, mas não poderá exceder 50M (mx). No caso de máximo, a memória total é de 50M e o tamanho livre é de 50M. Quanto ao tamanho mínimo (mn), se o heap não for muito usado, o jvm poderá reduzir o tamanho do heap para 10M.

Este mecanismo é para eficiência de memória. Se um programa java pequeno for executado em uma enorme memória heap de tamanho fixo, muita memória poderá ser um desperdício.


1

Você pode ver os resultados no formato MB , com a divisão de 1024 x 1024, que é igual a 1 MB .

int dataSize = 1024 * 1024;

System.out.println("Used Memory   : " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/dataSize + " MB");
System.out.println("Free Memory   : " + Runtime.getRuntime().freeMemory()/dataSize + " MB");
System.out.println("Total Memory  : " + Runtime.getRuntime().totalMemory()/dataSize + " MB");
System.out.println("Max Memory    : " + Runtime.getRuntime().maxMemory()/dataSize + " MB");  
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.