【问题标题】:Does java -Xmx1G mean 10^9 or 2^30 bytes?java -Xmx1G 是指 10^9 还是 2^30 字节?
【发布时间】:2015-12-27 15:25:26
【问题描述】:

一般来说,是用于-Xmx-Xms-Xmn 选项的单位(“k”、“M”和“G”,或者不太标准的可能性“K”、“m”或“g”)Binary prefix 倍数(即 1024 的幂),还是 1000 的幂?

手册说它们代表千字节 (kB)、兆字节 (MB) 和千兆字节 (GB),表明它们是原始 SI 系统中定义的 1000 的幂。我的非正式测试(我不太自信)表明它们确实是 kibibytes (kiB)mebibytes (MiB)gibibytes (GiB),都是 1024 的幂。

那么哪个是正确的?例如。什么 Java 代码会显示当前大小?

对于 RAM 大小而言,使用 1024 的倍数并不奇怪,因为 RAM 通常是通过加倍硬件模块进行物理布局的。但是随着权力越来越大,以清晰和标准的方式使用单位变得越来越重要,因为混乱的可能性也在增加。我的 JVM 也接受单位“t”,1 TiB 比 1 TB 大 10%。

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

注意:有关选项用途的更多信息,请参见例如java - What are the Xms and Xmx parameters when starting JVMs?.

【问题讨论】:

  • @ElliottFrisch 主要是我在问这个问题,寻找一个明确的答案。文档建议只是为了更清楚地说明我的困惑。

标签: java units-of-measurement


【解决方案1】:

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

长答案:

This documentation page on the command line arguments 表示以下适用于所有接受内存大小的参数:

例如,要将大小设置为 8 GB,您可以指定 8g8192m8388608k8589934592 作为参数。

对于-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;
  }
}

KMG 这些常量在src/share/vm/utilities/globalDefinitions.hpp 中定义:

const size_t K                  = 1024;
const size_t M                  = K*K;
const size_t G                  = M*K;

所有这些都证实了文档,除了对 TB 的 T 后缀的支持显然是后来添加的,根本没有记录。

不强制使用单位乘数,所以如果你想要十亿字节,你可以写-Xmx1000000000。如果你确实使用了乘数,它们是二进制的,所以-Xmx1G 表示 230 字节,或者一根内存条。

(这并不奇怪,因为 Java 早于 IEC 追溯重新定义现有单词的尝试。如果 IEC 仅建议使用限定符“二进制”和“十进制”来消除内存单元的歧义,则可以避免混淆有时它们的含义不清楚。例如,二进制千兆字节 (GB2) = 10243 字节,十进制千兆字节 (GB10) = 10003 字节。但是不,他们重新定义了每个人已经在使用的词,不可避免地引发混乱,让我们被这些小丑困住术语“gibibyte”、“tebibyte”等等。哦,上帝保佑我们。)

【讨论】:

  • 感谢您找到代码!非常清楚。但我必须指出,是计算机人员重新定义了两个多世纪以前的明确术语。让 IEC 保留它们已经使用了这么长时间,并为新单位提供新的术语,这对我来说很有意义。 MiB 比“二进制兆字节”或“MB_2”要简单得多,而且更容易格式化、翻译等。
  • 感谢您找到该文档。与我在我的系统(Ubuntu)和我的网络搜索中找到的文档相比,它有更清晰的示例来阐明它们对 MB 和 GB 的使用。看起来他们已经澄清了,也许是 Java 8 :)
  • 对于 Oracle Java 8,情况很奇怪。设置 -Xmx8g 最终得到 7.11 GiB(7635730432 字节)的 maxMemory... 使用 Java 11 我得到了完整的 8GiB。
【解决方案2】:

您有两种选择来回答您的问题:

a) 检查 JDK 的源代码。抱歉,我无法在 5 分钟内搜索到它。

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

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

并运行几次:

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

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

【讨论】:

    【解决方案3】:

    在另一个关于-Xmx 标志的question 中,Runtime.getRuntime().maxMemory() 用于显示当前大小。还需要注意的是,-Xmx1024m-Xmx1g 产生相同的输出,表明数字是 2 的幂,而不是 10 的幂。

    还要注意totalMemory()maxMemory() 之间的区别。
    What are Runtime.getRuntime().totalMemory() and freeMemory()?

    【讨论】:

    • 你提到的问题是正确的!请特别查看class MemTest by Alex,了解非堆内存(包括代码缓存和永久代池)与堆内存(包括伊甸园空间、幸存者空间和永久代池)的完整对比
    猜你喜欢
    • 2011-08-24
    • 2015-05-28
    • 1970-01-01
    • 2013-10-13
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多