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 Virtual Machine การเรียกใช้เมธอด gc อาจส่งผลให้เพิ่มค่าที่ส่งคืนโดย freeMemory

อ้างอิงถึงคำถามของคุณmaxMemory()คืน-Xmxค่า

คุณอาจจะสงสัยว่าทำไมมีtotalMemory ()และmaxMemory () คำตอบคือ JVM จัดสรรหน่วยความจำอย่างเกียจคร้าน ให้บอกว่าคุณเริ่มกระบวนการ Java ของคุณเช่น:

java -Xms64m -Xmx1024m Foo

กระบวนการของคุณเริ่มต้นด้วยหน่วยความจำ 64mb และถ้าและเมื่อใดก็ตามที่ต้องการเพิ่มเติม (สูงถึง 1024m) กระบวนการจะจัดสรรหน่วยความจำ totalMemory()สอดคล้องกับปริมาณของหน่วยความจำที่มีอยู่ในปัจจุบันสำหรับ JVM สำหรับ Foo ถ้า JVM ความต้องการหน่วยความจำมากขึ้นก็ขี้เกียจจะจัดสรรมันขึ้นกับหน่วยความจำสูงสุด หากคุณทำงานด้วย-Xms1024m -Xmx1024mค่าที่คุณได้รับจากtotalMemory()และmaxMemory()จะเท่ากัน

นอกจากนี้หากคุณต้องการคำนวณจำนวนหน่วยความจำที่ใช้อย่างถูกต้องคุณจะต้องทำการคำนวณดังต่อไปนี้:

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

-Xmxค่าดูเหมือนว่าจะส่งผลกระทบโดยตรงต่อการเริ่มต้นmaxMemory()ค่า แต่ฉันได้เห็นรายงานmaxMemory()เพิ่มขึ้นตามจำนวนเงินที่มีขนาดเล็กอาจ ~ 1% ในขณะที่โปรแกรมกำลังทำงาน
H2ONaCl

2
สิ่งนี้แตกต่างจากDebug.getNativeHeapFreeSize()อย่างไร
IgorGanapolsky

@ H2ONaCl ใช่มันอาจเปลี่ยนไปเล็กน้อยเนื่องจาก JVM UseAdaptiveSizePolicyเปิดใช้งานตามค่าเริ่มต้น และ BTW: maxMemory()= Xmx- ขนาดของพื้นที่ผู้รอดชีวิตเพียงคนเดียว ทำไม? เนื่องจากในเวลาเดียวกันสามารถใช้พื้นที่ผู้รอดชีวิตเพียงแห่งเดียวเท่านั้น
G. Demecki

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


1
แตกต่างจากนี้Debug.getMemoryInfo()ไหม
IgorGanapolsky

1
หมายเหตุ: หน่วยความจำที่ใช้แล้วอาจไม่มีวัตถุอ้างอิงอีกต่อไปซึ่งจะถูกกวาดล้างโดย GC ถัดไป
Gab 是好人

@cheneym หน่วยความจำที่ว่างและไม่ได้จัดสรรจะถูกครอบครองเนื่องจากคำแนะนำโค้ด Java byte จะถูกประมวลผลโดยโปรเซสเซอร์หาก "Xmx - Usedmemory" เป็น avlbl ในเครื่อง Xmx นั้นเหมือนกับ ballon ที่สามารถเติมอากาศที่ได้จาก avlbl ในเครื่องได้ทันทีที่ได้รับอากาศมันจะถูกเติมเต็มและจะระเบิดเมื่อเกินขีด จำกัด Xmx แต่สมาชิกทั้งหมดจะไม่บอกหน่วยความจำ avbl ที่แท้จริงในเครื่องสำหรับ JVM แต่มี nmbr.Is มีวิธีใดที่ฉันสามารถหาหน่วยความจำ avlbl จริงในเครื่องเพื่อที่ฉันจะได้รู้ว่าหน่วยความจำ rqd เป็น avlbl หรือไม่สำหรับ JVM remaning กระบวนการ?
มาเรีย

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

Runtime # totalMemory - หน่วยความจำที่ JVM ได้จัดสรรไว้แล้ว สิ่งนี้ไม่จำเป็นต้องมีการใช้งานหรือสูงสุด

Runtime # maxMemory - จำนวนหน่วยความจำสูงสุดที่ JVM ได้รับการกำหนดค่าให้ใช้ เมื่อกระบวนการของคุณถึงจำนวนนี้ JVM จะไม่จัดสรรมากขึ้นและแทนที่ GC บ่อยขึ้น

Runtime # freeMemory - ฉันไม่แน่ใจว่าสิ่งนี้วัดจากค่าสูงสุดหรือส่วนของผลรวมที่ไม่ได้ใช้ ฉันเดาว่ามันคือการวัดส่วนของทั้งหมดที่ไม่ได้ใช้


5

ขนาดฮีป JVM สามารถเติบโตได้และลดขนาดได้โดยกลไกการเก็บขยะ แต่ไม่สามารถจัดสรรเกินขนาดหน่วยความจำสูงสุด: Runtime.maxMemory นี่คือความหมายของหน่วยความจำสูงสุด หน่วยความจำทั้งหมดหมายถึงขนาดฮีปที่จัดสรร และหน่วยความจำที่ว่างหมายถึงขนาดที่มีอยู่ในหน่วยความจำทั้งหมด

ตัวอย่าง) java -Xms20M -Xmn10M -Xmx50M ~~~ ซึ่งหมายความว่า jvm ควรจัดสรรฮีป 20M เมื่อเริ่มต้น (ms) ในกรณีนี้หน่วยความจำทั้งหมดคือ 20M หน่วยความจำว่างคือขนาดที่ใช้ 20M หากต้องการฮีปเพิ่มเติม JVM จะจัดสรรมากกว่า แต่ไม่เกิน 50M (mx) ในกรณีสูงสุดหน่วยความจำทั้งหมดคือ 50M และขนาดที่ว่างคือขนาดที่ใช้ 50M สำหรับขนาด minumum (mn) หากไม่ใช้ฮีปมาก jvm สามารถลดขนาดฮีปเป็น 10M

กลไกนี้มีไว้สำหรับประสิทธิภาพของหน่วยความจำ หากโปรแกรมจาวาขนาดเล็กทำงานบนหน่วยความจำฮีปขนาดใหญ่แน่นอนหน่วยความจำจำนวนมากอาจสิ้นเปลือง


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");  
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.