Runtime.getR.78 (). TotalMemory () và freeMemory () là gì?


Câu trả lời:


195

Theo API

totalMemory()

Trả về tổng dung lượng bộ nhớ trong máy ảo Java. Giá trị được trả về bởi phương thức này có thể thay đổi theo thời gian, tùy thuộc vào môi trường máy chủ. Lưu ý rằng dung lượng bộ nhớ cần thiết để giữ một đối tượng thuộc bất kỳ loại đã cho nào có thể phụ thuộc vào việc triển khai.

maxMemory()

Trả về dung lượng bộ nhớ tối đa mà máy ảo Java sẽ cố sử dụng. Nếu không có giới hạn vốn có thì giá trị Long.MAX_VALUE sẽ được trả về.

freeMemory()

Trả về dung lượng bộ nhớ trống trong Máy ảo Java. Gọi phương thức gc có thể dẫn đến tăng giá trị được trả về bởi freeMemory.

Để tham khảo câu hỏi của bạn, maxMemory()trả về -Xmxgiá trị.

Bạn có thể tự hỏi tại sao có TotalMemory ()maxMemory () . Câu trả lời là JVM phân bổ bộ nhớ một cách lười biếng. Hãy nói rằng bạn bắt đầu quá trình Java của mình như vậy:

java -Xms64m -Xmx1024m Foo

Quá trình của bạn bắt đầu với 64mb bộ nhớ và nếu và khi cần nhiều hơn (tối đa 1024m), nó sẽ phân bổ bộ nhớ. totalMemory()tương ứng với dung lượng bộ nhớ hiện có cho JVM cho Foo. Nếu JVM cần thêm bộ nhớ, nó sẽ phân bổ nó một cách lười biếng lên tới bộ nhớ tối đa. Nếu bạn chạy với -Xms1024m -Xmx1024m, giá trị bạn nhận được totalMemory()maxMemory()sẽ bằng nhau.

Ngoài ra, nếu bạn muốn tính toán chính xác dung lượng bộ nhớ đã sử dụng , bạn thực hiện với phép tính sau:

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

Các -Xmxgiá trị dường như trực tiếp ảnh hưởng ban đầu maxMemory()giá trị tuy nhiên tôi đã thấy được báo cáo maxMemory()tăng một lượng nhỏ, có lẽ ~ 1%, trong khi chương trình đang chạy.
H2ONaCl

2
Điều này khác với Debug.getNativeHeapFreeSize()như thế nào?
IgorGanapolsky

@ H2ONaCl có, nó có thể thay đổi một chút, vì JVM UseAdaptiveSizePolicyđược bật theo mặc định. Và BTW: maxMemory()= Xmx- kích thước của một không gian sống sót duy nhất. Tại sao? Bởi vì cùng một lúc, chỉ có một không gian sống sót có thể được sử dụng.
G. Demecki 17/03/2017

236

Tên và giá trị là khó hiểu. Nếu bạn đang tìm kiếm tổng bộ nhớ trống, bạn sẽ phải tự tính toán giá trị này. Nó không phải là những gì bạn nhận được từ freeMemory();.

Xem hướng dẫn sau:

Tổng bộ nhớ được chỉ định , giá trị này sẽ bằng với giá trị -Xmx được định cấu hình :

Runtime.getR.78 (). MaxMemory ();

Bộ nhớ trống được phân bổ hiện tại, là không gian được phân bổ hiện tại sẵn sàng cho các đối tượng mới. Chú ý đây không phải là tổng số miễn phí có sẵn bộ nhớ:

Runtime.getR.78 (). FreeMemory ();

Tổng bộ nhớ được phân bổ , là tổng dung lượng được phân bổ dành riêng cho quá trình java:

Runtime.getR.78 (). TotalMemory ();

Bộ nhớ đã sử dụng , phải được tính toán:

usedMemory = Runtime.getR.78 (). totalMemory () - Runtime.getR.78 (). freeMemory ();

Tổng bộ nhớ trống , phải được tính:

freeMemory = Runtime.getR.78 (). maxMemory () - usedMemory;

Một hình ảnh có thể giúp làm rõ:

bộ nhớ thời gian chạy java


1
Đây có phải là khác nhau Debug.getMemoryInfo()?
IgorGanapolsky

1
Lưu ý: Bộ nhớ đã sử dụng có thể không chứa các đối tượng được tham chiếu nữa sẽ bị quét bởi GC tiếp theo.
Gab

@cheneym, bộ nhớ miễn phí và không được phân bổ sẽ bị chiếm dụng vì các hướng dẫn mã byte java sẽ chỉ được xử lý bởi bộ xử lý nếu "Xmx - usedmemory" có sẵn trong máy. Xmx giống như công suất tối đa của ballon có thể lấp đầy không khí từ không khí avlbl trong chính máy, ngay khi nó có không khí, nó sẽ được lấp đầy và sẽ nổ khi vượt quá giới hạn Xmx. Nhưng tổng số tự do sẽ không nói với bộ nhớ avbl thực tế trong máy cho JVM, mà chỉ là nmbr. Có cách nào tôi có thể tìm ra bộ nhớ avlbl thực tế trong máy để tôi có thể biết liệu bộ nhớ rqd có phải là avlbl hay không cho JVM quá trình ?
Maria

12

Để hiểu rõ hơn, hãy chạy chương trình sau đây (trong jdk1.7.x):

$ java -Xms1025k -Xmx1025k -XshowSettings:vm  MemoryTest

Điều này sẽ in các tùy chọn jvm và bộ nhớ đã sử dụng , miễn phí , tổngtối đa có sẵn trong 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

Phiên bản được mã hóa của tất cả các câu trả lời khác (tại thời điểm viết):

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

Thời gian chạy # TotalMemory - bộ nhớ mà JVM đã phân bổ cho đến nay. Đây không nhất thiết là những gì đang sử dụng hoặc tối đa.

Runtime # maxMemory - dung lượng bộ nhớ tối đa mà JVM đã được cấu hình để sử dụng. Khi quy trình của bạn đạt đến số tiền này, JVM sẽ không phân bổ nhiều hơn và thay vào đó, GC thường xuyên hơn nhiều.

Thời gian chạy # freeMemory - Tôi không chắc chắn nếu điều này được đo từ mức tối đa hoặc phần của tổng số không được sử dụng. Tôi đoán nó là một phép đo của tổng số không được sử dụng.


5

Kích thước heap JVM có thể phát triển và thu nhỏ được bằng cơ chế Garbage-Collection. Nhưng, nó không thể phân bổ trên kích thước bộ nhớ tối đa: Runtime.maxMemory. Đây là ý nghĩa của bộ nhớ tối đa. Tổng bộ nhớ có nghĩa là kích thước heap được phân bổ. Và bộ nhớ trống có nghĩa là kích thước có sẵn trong tổng bộ nhớ.

ví dụ) java -Xms20M -Xmn10M -Xmx50M ~~~. Điều này có nghĩa là jvm nên phân bổ heap 20M khi bắt đầu (ms). Trong trường hợp này, tổng bộ nhớ là 20M. bộ nhớ trống là kích thước 20M sử dụng. Nếu cần nhiều heap, JVM phân bổ nhiều hơn nhưng không thể vượt quá 50M (mx). Trong trường hợp tối đa, tổng bộ nhớ là 50M và kích thước miễn phí là kích thước sử dụng 50M. Đối với kích thước tối thiểu (mn), nếu heap không được sử dụng nhiều, jvm có thể thu nhỏ kích thước heap xuống còn 10M.

Cơ chế này là cho hiệu quả của bộ nhớ. Nếu chương trình java nhỏ chạy trên bộ nhớ heap kích thước cố định lớn, thì rất nhiều bộ nhớ có thể gây lãng phí.


1

Bạn có thể xem kết quả ở định dạng MB , với cách chia 1024 x 1024 tương đương với 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");  
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.