Apa itu Runtime.getRuntime (). TotalMemory () dan freeMemory ()?


Jawaban:


195

Menurut API

totalMemory()

Mengembalikan jumlah total memori di mesin virtual Java. Nilai yang dikembalikan oleh metode ini dapat bervariasi dari waktu ke waktu, tergantung pada lingkungan host. Perhatikan bahwa jumlah memori yang diperlukan untuk memegang objek dari jenis apa pun mungkin bergantung pada implementasi.

maxMemory()

Mengembalikan jumlah maksimum memori yang akan coba digunakan oleh mesin virtual Java. Jika tidak ada batas bawaan, maka nilai Long.MAX_VALUE akan dikembalikan.

freeMemory()

Mengembalikan jumlah memori bebas di Java Virtual Machine. Memanggil metode gc dapat mengakibatkan peningkatan nilai yang dikembalikan oleh freeMemory.

Mengacu pada pertanyaan Anda, maxMemory()kembalikan -Xmxnilainya.

Anda mungkin bertanya-tanya mengapa ada totalMemory () DAN maxMemory () . Jawabannya adalah bahwa JVM mengalokasikan memori dengan malas. Katakanlah Anda memulai proses Java Anda seperti itu:

java -Xms64m -Xmx1024m Foo

Proses Anda dimulai dengan 64mb memori, dan jika dan ketika itu membutuhkan lebih banyak (hingga 1024m), itu akan mengalokasikan memori. totalMemory()sesuai dengan jumlah memori yang saat ini tersedia untuk JVM untuk Foo. Jika JVM membutuhkan lebih banyak memori, itu malas akan mengalokasikannya sampai ke memori maksimal. Jika Anda menjalankan dengan -Xms1024m -Xmx1024m, nilai yang Anda dapatkan dari totalMemory()dan maxMemory()akan sama.

Selain itu, jika Anda ingin menghitung secara akurat jumlah memori yang digunakan , Anda melakukannya dengan perhitungan berikut:

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

The -Xmxnilai tampaknya secara langsung mempengaruhi awal maxMemory()nilai namun saya telah melihat dilaporkan maxMemory()meningkat dengan jumlah yang kecil, mungkin ~ 1%, sementara program ini berjalan.
H2ONaCl

2
Bagaimana ini berbeda Debug.getNativeHeapFreeSize()?
IgorGanapolsky

@ H2ONaCl ya, mungkin sedikit berubah, karena JVM UseAdaptiveSizePolicydiaktifkan secara default. Dan BTW: maxMemory()= Xmx- ukuran satu ruang selamat. Mengapa? Karena pada saat yang sama, hanya satu ruang selamat yang dapat digunakan.
G. Demecki

236

Nama dan nilainya membingungkan. Jika Anda mencari total memori bebas, Anda harus menghitung sendiri nilai ini. Bukan apa yang Anda dapatkan freeMemory();.

Lihat panduan berikut:

Total memori yang ditunjuk , ini akan sama dengan nilai -Xmx yang dikonfigurasi :

Runtime.getRuntime (). MaxMemory ();

Memori bebas yang dialokasikan saat ini , adalah ruang yang dialokasikan saat ini siap untuk objek baru. Perhatian ini bukan total memori yang tersedia :

Runtime.getRuntime (). FreeMemory ();

Total alokasi memori , adalah total alokasi ruang yang disediakan untuk proses java:

Runtime.getRuntime (). TotalMemory ();

Memori yang digunakan , harus dihitung:

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

Total memori bebas , harus dihitung:

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

Gambar dapat membantu memperjelas:

memori java runtime


1
Apakah ini berbeda Debug.getMemoryInfo()?
IgorGanapolsky

1
Catatan: Memori yang digunakan mungkin tidak lagi berisi objek referensi yang akan tersapu oleh GC berikutnya.
Gab 是 好人

@cheneym, memori bebas dan tidak terisi akan ditempati karena instruksi kode byte java akan diproses oleh prosesor hanya jika "Xmx - Usedmemory" adalah avlbl di mesin. Xmx seperti ballon kapasitas maksimum yang dapat diisi dengan udara yang keluar dari udara avlbl di dalam mesin itu sendiri, segera setelah mendapat udara, itu akan terisi dan akan meledak setelah melampaui batas Xmx. Tapi total freememory tidak akan memberitahu memori avbl yang sebenarnya dalam mesin untuk JVM, tetapi hanya nmbr. Apakah ada cara saya bisa mengetahui memori avlbl yang sebenarnya dalam mesin sehingga saya bisa mengetahui apakah memori rqd avlbl atau tidak untuk remaning JVM proses?
Maria

12

Untuk memahaminya dengan lebih baik, jalankan program berikut ini (di jdk1.7.x):

$ java -Xms1025k -Xmx1025k -XshowSettings:vm  MemoryTest

Ini akan mencetak opsi jvm dan memori yang digunakan , gratis , total , dan maksimum yang tersedia di 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

Versi yang dikodifikasikan dari semua jawaban lain (pada saat penulisan):

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

Runtime # totalMemory - memori yang telah dialokasikan JVM sejauh ini. Ini belum tentu apa yang digunakan atau maksimal.

Runtime # maxMemory - jumlah maksimum memori yang telah dikonfigurasi untuk digunakan oleh JVM. Setelah proses Anda mencapai jumlah ini, JVM tidak akan mengalokasikan lebih banyak dan sebaliknya GC lebih sering.

Runtime # freeMemory - Saya tidak yakin apakah ini diukur dari maks atau bagian dari total yang tidak digunakan. Saya menduga itu adalah pengukuran porsi total yang tidak digunakan.


5

Ukuran tumpukan JVM dapat ditumbuhkan dan menyusut oleh mekanisme Pengumpulan Sampah. Tapi, itu tidak dapat mengalokasikan lebih dari ukuran memori maksimum: Runtime.maxMemory. Ini adalah arti dari memori maksimum. Memori total berarti ukuran tumpukan yang dialokasikan. Dan membebaskan memori berarti ukuran yang tersedia dalam memori total.

contoh) java -Xms20M -Xmn10M -Xmx50M ~~~. Ini berarti bahwa jvm harus mengalokasikan tumpukan 20M saat mulai (ms). Dalam hal ini, total memori adalah 20M. memori bebas adalah ukuran yang digunakan 20M. Jika lebih banyak tumpukan diperlukan, JVM mengalokasikan lebih banyak tetapi tidak bisa lebih dari 50M (mx). Dalam kasus maksimum, memori total adalah 50M, dan ukuran bebas adalah ukuran yang digunakan 50M. Sedangkan untuk ukuran minumum (mn), jika heap tidak banyak digunakan, jvm dapat menyusutkan ukuran heap menjadi 10M.

Mekanisme ini untuk efisiensi memori. Jika program java kecil berjalan di memori tumpukan ukuran tetap besar, begitu banyak memori mungkin sia-sia.


1

Anda dapat melihat hasilnya dalam format MB , dengan pembagian 1024 x 1024 yang sama dengan 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");  
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.