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

Ответы:

195

Согласно API

totalMemory()

Возвращает общий объем памяти в виртуальной машине Java. Значение, возвращаемое этим методом, может изменяться со временем в зависимости от среды хоста. Обратите внимание, что объем памяти, необходимый для хранения объекта любого данного типа, может зависеть от реализации.

maxMemory()

Возвращает максимальный объем памяти, который будет пытаться использовать виртуальная машина Java. Если нет внутреннего ограничения, то будет возвращено значение Long.MAX_VALUE.

freeMemory()

Возвращает количество свободной памяти в виртуальной машине Java. Вызов метода gc может привести к увеличению значения, возвращаемого freeMemory.

В ответ на ваш вопрос maxMemory()возвращает -Xmxзначение.

Вы можете задаться вопросом, почему существует totalMemory () И maxMemory () . Ответ в том, что JVM распределяет память лениво. Допустим, вы запускаете свой процесс Java как таковой:

java -Xms64m -Xmx1024m Foo

Ваш процесс начинается с 64 МБ памяти, и если и когда ему потребуется больше (до 1024 м), он выделит память. totalMemory()соответствует количеству памяти в настоящее время доступного для виртуальной машины Java для Foo. Если JVM потребуется больше памяти, она будет лениво распределять ее до максимального объема памяти. Если вы работаете с -Xms1024m -Xmx1024m, значение, которое вы получите, totalMemory()и maxMemory()будет равно.

Кроме того, если вы хотите точно рассчитать объем используемой памяти, выполните следующие вычисления:

final long usedMem = totalMemory() - freeMemory();
Амир Афганский
источник
-XmxЗначение , кажется, напрямую влияет на первоначальное maxMemory()значение , однако я видел Зафиксирован maxMemory()рост на небольшую величину, возможно , ~ 1%, в то время как программа работает.
H2ONaCl
2
Чем это отличается от Debug.getNativeHeapFreeSize()?
Игорь Ганапольский
@ H2ONaCl Да, это может немного измениться, потому что JVM UseAdaptiveSizePolicyвключены по умолчанию. И кстати: 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 () - usedMemory;

Картинка может помочь уточнить:

память времени выполнения Java

cheneym
источник
1
Это отличается от Debug.getMemoryInfo()?
Игорь Ганапольский
1
Примечание. Используемая память может содержать объекты, на которые больше не ссылаются, которые будут сметены следующим GC.
Габ 是 好人
@cheneym, свободная и нераспределенная память будет занята, так как инструкции по байт-коду Java будут обрабатываться процессором только в том случае, если на компьютере имеется «Xmx - Usedmemory». 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");            
        }
}
Sriram
источник
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());
    }
}
TWiStErRob
источник
7

Runtime # totalMemory - память, выделенная JVM до сих пор. Это не обязательно то, что используется или максимум.

Runtime # maxMemory - максимальный объем памяти, который JVM сконфигурировал для использования. Как только ваш процесс достигнет этой суммы, JVM не будет выделять больше, а вместо этого GC будет гораздо чаще.

Runtime # freeMemory - я не уверен, измеряется ли это от максимума или части неиспользованной суммы. Я предполагаю, что это измерение той части общего количества, которая не используется.

Тим Бендер
источник
5

Размер кучи JVM может быть увеличен и уменьшен с помощью механизма сборки мусора. Но он не может распределяться по максимальному объему памяти: Runtime.maxMemory. В этом смысл максимальной памяти. Общий объем памяти означает выделенный размер кучи. И свободная память означает доступный объем в общей памяти.

пример) java -Xms20M -Xmn10M -Xmx50M ~~~. Это означает, что jvm должен выделить кучу 20M при запуске (мс). В этом случае общая память составляет 20M. объем свободной памяти составляет 20M. Если требуется больше кучи, JVM выделяет больше, но не может превышать 50M (mx). В случае максимума общий объем памяти составляет 50 МБ, а свободный размер равен 50 МБ. Что касается минимального размера (mn), если куча не используется много, jvm может уменьшить размер кучи до 10M.

Этот механизм для эффективности памяти. Если небольшая Java-программа запускается на огромной куче памяти фиксированного размера, такой объем памяти может быть расточительным.

Алам-Ким
источник
1

Вы можете увидеть результаты в формате MB , с делением 1024 x 1024, что равно 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");  
Габриэль Лопес
источник