Що таке Runtime.getRuntime (). TotalMemory () та freeMemory ()?


146

Мені було цікаво, що точне значення Runtime.getRuntime (). TotalMemory () , Runtime.getRuntime (). FreeMemory () і Runtime.getRuntime (). MaxMemory () .

Я розумію, Runtime.getRuntime().totalMemory()повертає загальну пам'ять, яку використовує мій процес. Це правильно?

Як щодо freeMemory()і maxMemory()?

Відповіді:


195

Згідно з API

totalMemory()

Повертає загальний об'єм пам'яті у віртуальній машині Java. Значення, що повертається цим методом, може змінюватися з часом, залежно від середовища перебування. Зауважте, що обсяг пам'яті, необхідний для вмісту об'єкта будь-якого типу, може залежати від реалізації.

maxMemory()

Повертає максимальний об'єм пам'яті, яку намагатиметься використовувати віртуальна машина Java. Якщо немає властивого обмеження, то значення Long.MAX_VALUE повернеться.

freeMemory()

Повертає кількість вільної пам'яті у віртуальній машині Java. Виклик методу gc може призвести до збільшення значення, поверненого freeMemory.

Посилаючись на ваше запитання, maxMemory()повертає -Xmxзначення.

Вам може бути цікаво, чому існує загальна Пам'ять () І maxMemory () . Відповідь - JVM виділяє пам'ять ліниво. Скажімо, ви запускаєте процес Java як такий:

java -Xms64m -Xmx1024m Foo

Ваш процес починається з 64 Мб пам'яті, і якщо і коли йому потрібно більше (до 1024 м), він виділить пам'ять. totalMemory()відповідає обсягу пам'яті, доступної в даний час в JVM для Foo. Якщо JVM потрібно більше пам'яті, він ліниво виділити його до до максимальної пам'яті. Якщо ви працюєте з -Xms1024m -Xmx1024m, значення, яке ви отримаєте, totalMemory()і maxMemory()буде рівним.

Крім того, якщо ви хочете точно обчислити об'єм використовуваної пам'яті, зробіть це за допомогою наступного розрахунку:

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

-XmxЗначення , здається, безпосередньо впливає на початкове maxMemory()значення , однак я бачив Зафіксовано maxMemory()зростання на невелику величину, можливо , ~ 1%, в той час як програма працює.
H2ONaCl

2
Чим це відрізняється від Debug.getNativeHeapFreeSize()?
ІгорГанапольський

@ H2ONaCl так, це може трохи змінитися, оскільки JVM UseAdaptiveSizePolicyувімкнено за замовчуванням. І BTW: maxMemory()= Xmx- розмір одного простору для виживання. Чому? Тому що в той же час можна використовувати лише один простір, що вижив.
Г. Демецький

236

Імена та значення заплутані. Якщо ви шукаєте загальну вільну пам'ять, вам доведеться вирахувати це значення самостійно. Це не те, від чого ти отримуєш freeMemory();.

Дивіться наступне керівництво:

Загальна призначена пам'ять , це буде дорівнює налаштованому значенню -Xmx :

Runtime.getRuntime (). MaxMemory ();

Поточна виділена вільна пам'ять - це поточний відведений простір, готовий для нових об’єктів. Увага: це не загальна вільна доступна пам'ять:

Runtime.getRuntime (). FreeMemory ();

Загальна виділена пам'ять - це загальний виділений простір, відведений для java-процесу:

Runtime.getRuntime (). TotalMemory ();

Використовувана пам'ять , повинна бути обчислена:

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

Повна вільна пам'ять , повинна бути обчислена:

freeMemory = Runtime.getRuntime (). maxMemory () - використовуєтьсяMemory;

Зображення може допомогти уточнити:

пам'ять часу Java


1
Чи відрізняється це від Debug.getMemoryInfo()?
ІгорГанапольський

1
Примітка: Використовувана пам'ять може не містити більше посилаються об'єктів, які будуть зміщені наступним GC.
Габ 是 好人

@cheneym, вільна і нерозподілена пам'ять буде зайнята, оскільки інструкції коду байтового коду Java будуть оброблятися процесором, тільки якщо "Xmx - Usedmemory" є avlbl в машині. Xmx - це як максимальна ємність балона, яка могла б заповнити повітря, що потрапляє з avlbl повітря в саму машину, як тільки воно потрапить повітря, воно заповниться і вибухне колись перевищить межу Xmx. Але загальна майна не скаже фактичну пам'ять avbl в машині для JVM, а лише nmbr.Існує будь-який спосіб, як я міг би дізнатися фактичну пам'ять avlbl в машині, щоб я міг дізнатися, чи є пам'ять rqd avlbl чи ні для ремонту JVM процес?
Марія

12

Щоб краще зрозуміти, запустіть наступну програму (в jdk1.7.x):

$ java -Xms1025k -Xmx1025k -XshowSettings:vm  MemoryTest

Це надрукує параметри jvm та використану , вільну , загальну та максимальну пам'ять, доступну в 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

Кодифікована версія всіх інших відповідей (на момент написання):

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

Час виконання # totalMemory - пам'ять, яку JVM виділив досі. Це не обов'язково те, що використовується або максимум.

Час виконання # maxMemory - максимальний об'єм пам'яті, який було налаштовано для використання JVM. Як тільки ваш процес досягне цієї кількості, JVM не виділяє більше, а натомість GC набагато частіше.

Виконання # freeMemory - я не впевнений, чи вимірюється це від максимуму або частки від загальної кількості, яка не використовується. Я здогадуюсь, це вимірювання частки загальної кількості, яка не використовується.


5

Розмір купи JVM може бути вирощений і стискається за допомогою механізму збору сміття. Але він не може виділити максимальний об'єм пам'яті: Runtime.maxMemory. Це значення максимальної пам'яті. Загальна пам'ять означає виділений розмір купи. А вільна пам'ять означає наявний розмір у загальній пам'яті.

приклад) java -Xms20M -Xmn10M -Xmx50M ~~~. Це означає, що jvm повинен виділити купу 20M на старті (мс). У цьому випадку загальна пам'ять становить 20М. вільна пам'ять розміром 20 Мб. Якщо потрібно більше купи, JVM виділяє більше, але не може перевищувати 50 М (mx). У випадку максимуму загальна пам'ять становить 50 М, а вільний розмір - розмір 50 М. Що стосується мінімального розміру (mn), якщо купа не використовується багато, jvm може зменшити розмір купи до 10М.

Цей механізм призначений для ефективності пам'яті. Якщо невелика програма java працює на величезній купі пам'яті фіксованого розміру, стільки пам’яті може бути марним.


1

Ви можете побачити результати у форматі МБ , з поділом 1024 х 1024, що дорівнює 1 МБ .

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");  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.