java -Xmx1G是指10 ^ 9还是2 ^ 30个字节?

nea*_*mcb 15 java units-of-measurement

而在一般情况,是用于单位-Xmx,-Xms-Xmn选项("K","M"和"G",或不太标准的可能性"K","m"或"G")的二进制前缀倍数(即,功率1024),还是1000的力量?

手册说它们代表千字节(kB),兆字节(MB)和千兆字节(GB),表明它们是原始SI系统中定义的1000的幂.我的非正式测试(我不是很自信)表明他们真的是kibibytes(kiB),mebibytes(MiB)gibibytes(GiB),所有权力都是1024.

哪个是对的?例如,什么Java代码会显示当前大小?

使用1024的倍数对于RAM大小来说并不奇怪,因为RAM通常通过加倍硬件模块来物理布局.但是,随着我们获得越来越大的权力,以明确和标准的方式使用单位变得越来越重要,因为混乱的可能性会增加.单位"t"也被我的JVM接受,1 TiB比1 TB大10%.

注意:如果这些确实是二进制倍数,我建议更新文档和用户界面以非常清楚,例如" 附加字母k或K表示kibibytes(1024字节)"或m或M表示mebibytes( 1048576字节) ".这就是采用的方法,例如在Ubuntu:UnitsPolicy - Ubuntu Wiki中.

注意:有关选项用途的更多信息,请参阅例如java - 启动JVM时Xms和Xmx参数是什么?.

Boa*_*ann 29

简短回答:JVM命令行参数使用的所有内存大小都以传统的二进制单位指定,其中千字节为1024字节,其他大小为1024.

答案很长:

命令行参数上的此文档页面说明以下内容适用于接受内存大小的所有参数:

例如,设置大小为8 GB,您可以指定8g,8192m,8388608k,或8589934592作为参数.

因为-Xmx,它给出了这些具体的例子:

以下示例显示如何使用各种单位将分配的内存的最大允许大小设置为80 MB:

-Xmx83886080
-Xmx81920k
-Xmx80m

在我考虑检查文档之前(我假设你已经有了?),我检查了HotSpot的源代码,发现内存值在src/share/vm/runtime/arguments.cpp中由函数解析atomull(这似乎代表"ASCII到内存,unsigned long long"):

// Parses a memory size specification string.
static bool atomull(const char *s, julong* result) {
  julong n = 0;
  int args_read = sscanf(s, JULONG_FORMAT, &n);
  if (args_read != 1) {
    return false;
  }
  while (*s != '\0' && isdigit(*s)) {
    s++;
  }
  // 4705540: illegal if more characters are found after the first non-digit
  if (strlen(s) > 1) {
    return false;
  }
  switch (*s) {
    case 'T': case 't':
      *result = n * G * K;
      // Check for overflow.
      if (*result/((julong)G * K) != n) return false;
      return true;
    case 'G': case 'g':
      *result = n * G;
      if (*result/G != n) return false;
      return true;
    case 'M': case 'm':
      *result = n * M;
      if (*result/M != n) return false;
      return true;
    case 'K': case 'k':
      *result = n * K;
      if (*result/K != n) return false;
      return true;
    case '\0':
      *result = n;
      return true;
    default:
      return false;
  }
}
Run Code Online (Sandbox Code Playgroud)

这些常数K,M,G定义在SRC /共享/ VM /实用程序/ globalDefinitions.hpp:

const size_t K                  = 1024;
const size_t M                  = K*K;
const size_t G                  = M*K;
Run Code Online (Sandbox Code Playgroud)

所有这些都证实了文档,除了T后来显然添加了对太字节后缀的支持,并且根本没有记录.

使用单位乘数不是强制性的,因此如果你想要10亿个字节,你可以写-Xmx1000000000.如果你使用乘数,它们是二进制的,所以-Xmx1G意味着2 30个字节,或者一个固定的RAM.

(这并不奇怪,因为Java早于IEC试图追溯重新定义现有单词.如果IEC仅仅建议使用限定符"二进制"和"十进制"来消除存储单元的歧义,偶尔会出现其含义,那么就可以节省混淆.不清楚.例如,二进制千兆字节(GB 2)= 1024 3字节,十进制千兆字节(GB 10)= 1000 3字节.但不,他们重新定义了每个人都在使用的单词,不可避免地爆炸混乱,让我们陷入困境这些小丑的术语是"gibibyte","tebibyte"和其他的.哦上帝饶了我们.)

  • 感谢您找到代码!非常清楚.但我必须指出,正是计算机人员重新定义了两个多世纪以前的明确的术语.对于IEC来说,保留它们已经使用了很长时间,并为新单元提供新的术语,对我来说各种各样的意义.与"二进制兆字节"或"MB_2"相比,MiB更加简单,并且更容易格式化,翻译等. (3认同)

ya_*_*ser 5

您有两种方法可以获得问题的答案:

a)检查JDK的源代码.抱歉,我无法在5分钟内谷歌.

b)编写模拟,运行几次并进行一些观察.

public class A {
  public static void main(String[] args) throws Exception {
    System.out.println("total: " + Runtime.getRuntime().totalMemory());
  }
}
Run Code Online (Sandbox Code Playgroud)

并运行几次:

java -Xms130m -Xmx2G A
total: 131072000
java -Xms131m -Xmx2G A
total: 132644864
java -Xms132m -Xmx2G A
total: 132644864
java -Xms133m -Xmx2G A
total: 134742016
java -Xms134m -Xmx2G A
total: 134742016
Run Code Online (Sandbox Code Playgroud)

所以有根据的猜测是java使用的不是一个确切的数字,而是你所要求数字的2 ^ n近似值.