【问题标题】:What are Runtime.getRuntime().totalMemory() and freeMemory()?什么是 Runtime.getRuntime().totalMemory() 和 freeMemory()?
【发布时间】:2010-08-26 00:15:03
【问题描述】:

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

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

freeMemory()maxMemory() 怎么样?

【问题讨论】:

    标签: java


    【解决方案1】:

    名称和值令人困惑。如果您正在寻找可用内存总量,您必须自己计算该值。 这不是你从freeMemory();得到的。

    请参阅以下指南:

    总指定内存,这将等于配置的 -Xmx 值:

    Runtime.getRuntime().maxMemory();

    当前分配的空闲内存,是当前为新对象分配的空间准备好注意这不是总的可用可用内存:

    Runtime.getRuntime().freeMemory();

    总分配内存,是为 java 进程分配的总空间保留

    Runtime.getRuntime().totalMemory();

    已用内存,必须计算:

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

    总可用内存,必须计算:

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

    一张图片可能有助于澄清:

    【讨论】:

    • 这和Debug.getMemoryInfo()有区别吗?
    • 注意:已用内存可能包含不再引用的对象,这些对象将被下一次 GC 清除。
    • @cheneym,只有当机器中的“Xmx - Usedmemory”为avlbl时,处理器才会处理java字节码指令,因此空闲和未定位的内存将被占用。 Xmx 就像气球的最大容量,它可以充满来自机器本身的 avlbl 空气的空气,一旦它获得空气,它将被填充并一旦超过 Xmx 限制就会爆炸。但是总空闲内存不会告诉JVM机器中的实际avbl内存,而只是nmbr。有什么办法可以找出机器中的实际avlbl内存,以便我可以知道rqd内存是否是用于JVM remaning的avlbl过程?
    【解决方案2】:

    根据API

    totalMemory()
    

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

    maxMemory()
    

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

    freeMemory()
    

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

    关于您的问题,maxMemory() 返回 -Xmx 值。

    您可能想知道为什么会有 totalMemory()ma​​xMemory()。答案是 JVM 延迟分配内存。假设您这样启动 Java 进程:

    java -Xms64m -Xmx1024m Foo
    

    您的进程以 64mb 内存开始,如果需要更多内存(最多 1024m),它将分配内存。 totalMemory() 对应于 Foo 的 JVM当前可用的内存量。如果 JVM 需要更多内存,它会延迟地将其 up 分配到最大内存。如果使用-Xms1024m -Xmx1024m 运行,则从totalMemory()maxMemory() 获得的值将相等。

    另外,如果您想准确计算已用内存的数量,您可以使用以下计算:

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

    【讨论】:

    • -Xmx 值似乎直接影响初始 maxMemory() 值,但是我看到报告的 maxMemory() 在程序运行时增加了少量,可能约为 1%。
    • 这与Debug.getNativeHeapFreeSize()有何不同?
    • @H2ONaCl 是的,它可能会略有变化,因为默认情况下启用 JVM 的 UseAdaptiveSizePolicy。顺便说一句:maxMemory() = Xmx - 单个幸存者空间的大小。为什么?因为同时只能使用一个幸存者空间。
    【解决方案3】:

    为了更好地理解它,运行以下程序(在 jdk1.7.x 中):

    $ java -Xms1025k -Xmx1025k -XshowSettings:vm  MemoryTest
    

    这将打印 jvm 选项和 usedfreetotalmaximum em> 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");            
            }
    }
    

    【讨论】:

      【解决方案4】:

      所有其他答案的编纂版本(在撰写本文时):

      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());
          }
      }
      

      【讨论】:

        【解决方案5】:

        Runtime#totalMemory - JVM 到目前为止分配的内存。这不一定是正在使用的或最大值。

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

        Runtime#freeMemory - 我不确定这是从最大值还是未使用的总数中测量的部分。我猜这是对未使用的总数部分的度量。

        【讨论】:

          【解决方案6】:

          JVM 堆大小可以通过垃圾收集机制进行增长和收缩。 但是,它不能分配超过最大内存大小:Runtime.maxMemory。这就是最大内存的意思。总内存是指分配的堆大小。而空闲内存是指总内存中的可用大小。

          示例)java -Xms20M -Xmn10M -Xmx50M ~~~。 这意味着 jvm 应该在 start(ms) 时分配堆 20M。在这种情况下,总内存为 20M。可用内存为 20M 已用大小。如果需要更多堆,JVM 分配更多但不能超过 50M(mx)。最大情况下,总内存为50M,空闲大小为50M-used size。至于minumum size(mn),如果heap用得不多,jvm可以把heap size缩小到10M。

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

          【讨论】:

            【解决方案7】:

            您可以看到 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");  
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-01-01
              • 1970-01-01
              • 2013-02-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多