Que sont Runtime.getRuntime (). TotalMemory () et freeMemory ()?

Réponses:

195

Selon l' API

totalMemory()

Renvoie la quantité totale de mémoire de la machine virtuelle Java. La valeur renvoyée par cette méthode peut varier dans le temps, en fonction de l'environnement hôte. Notez que la quantité de mémoire requise pour contenir un objet d'un type donné peut dépendre de l'implémentation.

maxMemory()

Renvoie la quantité maximale de mémoire que la machine virtuelle Java tentera d'utiliser. S'il n'y a pas de limite inhérente, la valeur Long.MAX_VALUE sera renvoyée.

freeMemory()

Renvoie la quantité de mémoire disponible dans la machine virtuelle Java. L'appel de la méthode gc peut entraîner une augmentation de la valeur renvoyée par freeMemory.

En référence à votre question, maxMemory()renvoie la -Xmxvaleur.

Vous vous demandez peut-être pourquoi il existe un totalMemory () ET un maxMemory () . La réponse est que la JVM alloue la mémoire paresseusement. Disons que vous démarrez votre processus Java en tant que tel:

java -Xms64m -Xmx1024m Foo

Votre processus commence avec 64 Mo de mémoire, et si et quand il en a besoin de plus (jusqu'à 1024 m), il allouera de la mémoire. totalMemory()correspond à la quantité de mémoire actuellement disponible pour la JVM pour Foo. Si la JVM a besoin de plus de mémoire, elle l'allouera paresseusement jusqu'à la mémoire maximale. Si vous exécutez avec -Xms1024m -Xmx1024m, la valeur que vous obtenez totalMemory()et maxMemory()sera égale.

De plus, si vous souhaitez calculer avec précision la quantité de mémoire utilisée , procédez comme suit:

final long usedMem = totalMemory() - freeMemory();
Amir Afghani
la source
La -Xmxvaleur semble affecter directement la maxMemory()valeur initiale , mais j'ai vu l' maxMemory()augmentation rapportée d'une petite quantité, peut-être ~ 1%, pendant que le programme est en cours d'exécution.
H2ONaCl
2
En quoi est-ce différent de Debug.getNativeHeapFreeSize()?
IgorGanapolsky
@ H2ONaCl oui, cela peut légèrement changer, car la JVM UseAdaptiveSizePolicyest activée par défaut. Et BTW: maxMemory()= Xmx- taille d'un seul espace de survivant. Pourquoi? Parce qu'en même temps, un seul espace survivant peut être utilisé.
G.Demecki
236

Les noms et les valeurs prêtent à confusion. Si vous recherchez la mémoire totale disponible vous devrez calculer vous-même cette valeur. Ce n'est pas ce que vous obtenez freeMemory();.

Consultez le guide suivant:

Mémoire totale désignée , cela équivaudra à la valeur -Xmx configurée :

Runtime.getRuntime (). MaxMemory ();

La mémoire libre allouée actuelle est l'espace alloué actuel prêt pour de nouveaux objets. Attention ce n'est pas le total gratuit mémoire disponible disponible :

Runtime.getRuntime (). FreeMemory ();

Mémoire allouée totale , est l'espace total alloué réservé au processus java:

Runtime.getRuntime (). TotalMemory ();

Mémoire utilisée doit être calculée:

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

Mémoire libre totale doit être calculée:

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

Une image peut aider à clarifier:

mémoire d'exécution Java

cheneym
la source
1
Est-ce différent de Debug.getMemoryInfo()?
IgorGanapolsky
1
Remarque: la mémoire utilisée peut ne plus contenir d'objets référencés qui seront balayés par le prochain GC.
Gab 是 好人
@cheneym, la mémoire libre et non localisée sera occupée car les instructions de code d'octet java ne seront traitées par le processeur que si "Xmx - Usedmemory" est avlbl dans la machine. Xmx est comme la capacité maximale du ballon qui pourrait se remplir d'air provenant de l'air avlbl dans la machine elle-même, dès qu'il aura de l'air, il sera rempli et explosera une fois dépassé la limite de Xmx. Mais la mémoire libre totale ne dira pas la mémoire avbl réelle dans la machine pour JVM, mais juste le nmbr.Il existe-t-il de toute façon que je pourrais trouver la mémoire avlbl réelle dans la machine afin que je puisse savoir si la mémoire rqd est avlbl ou non pour le remanage JVM processus?
Maria
12

Pour mieux le comprendre, exécutez ce programme suivant (dans jdk1.7.x):

$ java -Xms1025k -Xmx1025k -XshowSettings:vm  MemoryTest

Cela affichera les options jvm et la mémoire utilisée , libre , totale et maximale disponible dans 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");            
        }
}
Sriram
la source
8

Version codifiée de toutes les autres réponses (au moment de la rédaction):

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

Runtime # totalMemory - la mémoire que la JVM a allouée jusqu'à présent. Ce n'est pas nécessairement ce qui est utilisé ou le maximum.

Runtime # maxMemory - la quantité maximale de mémoire que la JVM a été configurée pour utiliser. Une fois que votre processus atteint ce montant, la JVM n'allouera pas plus et GC beaucoup plus fréquemment.

Runtime # freeMemory - Je ne sais pas si cela est mesuré à partir du maximum ou de la partie du total qui est inutilisée. Je suppose que c'est une mesure de la partie du total qui n'est pas utilisée.

Tim Bender
la source
5

La taille du tas JVM peut être augmentée et réduite par le mécanisme de récupération de place. Mais, il ne peut pas allouer au-dessus de la taille de mémoire maximale: Runtime.maxMemory. C'est le sens de la mémoire maximale. La mémoire totale signifie la taille du tas allouée. Et la mémoire libre signifie la taille disponible dans la mémoire totale.

exemple) java -Xms20M -Xmn10M -Xmx50M ~~~. Cela signifie que jvm doit allouer le tas 20M au démarrage (ms). Dans ce cas, la mémoire totale est de 20 Mo. la mémoire libre est de 20M de taille utilisée. Si plus de tas est nécessaire, la JVM en alloue plus mais ne peut pas dépasser 50 Mo (mx). Dans le cas du maximum, la mémoire totale est de 50 Mo et la taille libre est la taille utilisée de 50 Mo. En ce qui concerne la taille minimale (mn), si le tas n'est pas beaucoup utilisé, jvm peut réduire la taille du tas à 10M.

Ce mécanisme sert à l'efficacité de la mémoire. Si un petit programme Java s'exécute sur une énorme mémoire de tas de taille fixe, autant de mémoire peut être un gaspillage.

ALam-Kim
la source
1

Vous pouvez voir les résultats dans le format MB , avec la division de 1024 x 1024 , qui est égale à 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");  
GAbriel Lopez
la source