什么是Runtime.getRuntime()。totalMemory()和freeMemory()?

什么是Runtime.getRuntime()。totalMemory()和freeMemory()?

问题描述:

我一直在想知道Runtime.getRuntime().totalMemory(),Runtime.getRuntime().freeMemory()Runtime.getRuntime().maxMemory()的确切含义是什么。什么是Runtime.getRuntime()。totalMemory()和freeMemory()?

我的理解是,Runtime.getRuntime().totalMemory()返回我的进程正在使用的总内存。那是对的吗?

freeMemory()maxMemory()怎么样?

按照API

totalMemory() 

返回的存储器中的Java虚拟机的总量。此方法返回的值可能随时间而变化,具体取决于主机环境。 请注意,保存任何给定类型的对象所需的内存量可能取决于实现。

maxMemory() 

返回Java虚拟机尝试使用的最大内存量。如果没有固有限制,则返回值Long.MAX_VALUE。

freeMemory() 

返回Java虚拟机中的可用内存量。调用gc方法可能会增加freeMemory返回的值。

参照你的问题,maxMemory()返回-Xmx的值。

你可能会奇怪为什么有totalMemory()和A maxMemory()。答案是JVM懒懒地分配内存。比方说,你开始你的Java进程这样:

java -Xms64m -Xmx1024m Foo 

你的过程与64MB内存开始,如果当它需要多个(最多1024米),它将分配内存。 totalMemory()对应于可用于Foo的JVM的内存量当前为。如果JVM需要更多的内存,它会延迟分配以上到最大内存。如果使用-Xms1024m -Xmx1024m运行,则从totalMemory()maxMemory()获得的值将相等。

另外,如果你想精确计算的使用内存量,你用下面的计算这样做:

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

的' -Xmx'值似乎直接影响了最初的'maxMemory()'值,但我有在程序运行时看到报告的'maxMemory()'增加了一小部分,大约为1%。 – H2ONaCl 2016-01-17 03:11:07

+2

与'Debug.getNativeHeapFreeSize()'有什么不同? – 2016-04-22 16:23:19

+0

@ H2ONaCl是的,它可能会稍微改变,因为默认情况下启用了JVM的UseAdaptiveSizePolicy。顺便说一下:'maxMemory()'='Xmx' - 单个生存空间的大小。为什么?因为同时只能使用一个幸存者空间。 – 2017-03-17 11:13:56

Runtime#totalMemory - 即JVM迄今分配的内存。这不一定是使用中的或最大的。

Runtime#maxMemory - JVM配置使用的最大内存量。一旦你的流程达到了这个数量,JVM就不会更频繁地分配更多,而是GC。

Runtime#freeMemory - 我不确定这是从最大值还是未使用的总值中计算得出。我猜测这是对未使用的总体部分的衡量。

JVM堆大小可以通过垃圾收集机制增长和收缩。 但是,它不能分配超过最大内存大小:Runtime.maxMemory。这是最大内存的含义。内存总量意味着分配的堆大小。可用内存意味着内存总量的可用大小。

示例)java -Xms20M -Xmn10M -Xmx50M ~~~。 这意味着jvm应该在开始(ms)分配堆20M。在这种情况下,总内存为20M。空闲内存是20M使用的大小。如果需要更多的堆,JVM将分配更多,但不能超过50M(mx)。在最大的情况下,总内存为50M,可用大小为50M使用的大小。至于最小规模(mn),如果堆不够用,jvm可以将堆大小缩小到10M。

这种机制是为了提高内存效率。如果小的Java程序运行在巨大的固定大小的堆内存上,那么太多的内存可能会浪费。

为了更好地理解它,运行这个程序之后(在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");    
     } 
} 

名称和数值很混乱。如果你正在寻找总空闲内存你将不得不自己计算这个值。 这不是你从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 runtime memory

+1

这与'Debug.getMemoryInfo()'不同吗? – 2016-04-22 16:24:52

+0

注意:**已用内存**可能**不再包含将被下一个GC清除的引用对象**。 – 2016-12-01 14:05:24

+0

@cheneym真棒回答!你启发了http://*.com/a/42567450/253468 – TWiStErRob 2017-03-02 22:51:06

编码化所有其他答案的版本(在写作时):

import java.io.*; 

/** 
* This class is based on <a href="http://*.com/users/2478930/cheneym">cheneym</a>'s 
* <a href="http://*.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://*.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()); 
    } 
}