一般而言,用于-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代码会显示当前大小?
使用1024的倍数对于RAM大小来说并不奇怪,因为RAM通常是通过加倍硬件模块来物理布局的。但是,随着我们获得越来越大的权力,以明确和标准的方式使用单位变得越来越重要,因为混乱的可能性会增加。单位" t"我的JVM也接受了,1 TiB比1 TB大10%。
注意:如果这些确实是二进制倍数,我建议更新文档和用户界面,以便非常清楚,例如" 附加字母k或K以表示kibibytes(1024字节) ,或m或M表示mebibytes(1048576字节)"。这就是采用的方法,例如在Ubuntu中:UnitsPolicy - Ubuntu Wiki。
注意:有关选项用途的更多信息,请参阅例如java - What are the Xms and Xmx parameters when starting JVMs?
答案 0 :(得分:24)
简短回答:JVM命令行参数使用的所有内存大小都以传统的二进制单位指定,其中千字节为1024字节,其他单位的增加功率为1024.
答案很长:
This documentation page on the command line arguments表示以下内容适用于接受内存大小的所有参数:
例如,要将大小设置为8 GB,您可以指定
8g
,8192m
,8388608k
或8589934592
作为参数。
对于-Xmx
,它提供了以下具体示例:
以下示例显示如何使用各种单位将分配的内存的最大允许大小设置为80 MB:
-Xmx83886080
-Xmx81920k
-Xmx80m
在我考虑检查文档之前(我假设你已经有了?),我检查了HotSpot的源代码,发现函数atomull
在src/share/vm/runtime/arguments.cpp中解析了内存值(这似乎是代表“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;
}
}
这些常量K
,M
,G
在src/share/vm/utilities/globalDefinitions.hpp中定义:
const size_t K = 1024;
const size_t M = K*K;
const size_t G = M*K;
所有这些都证实了文档,除了terabytes的T
后缀的支持显然在以后添加,并且根本没有记录。
使用单位乘数不是必须的,所以如果你想要 10亿字节,你可以写-Xmx1000000000
。如果你使用乘数,它们是二进制的,所以-Xmx1G
意味着2 30 字节,或者一个简称RAM。
(这并不奇怪,因为Java早于IEC试图追溯重新定义现有单词。如果IEC仅建议使用限定符“二进制”和“十进制”消除内存单元的歧义,则可以节省混淆。偶尔他们的意思不明确。例如,二进制千兆字节(GB 2 )= 1024 3 字节,十进制千兆字节(GB 10 )= 1000 3 字节。但不,他们重新定义了每个人都在使用的词,不可避免地爆发了混乱,让我们陷入这些小丑术语“gibibyte”,“tebibyte”和其他。哦上帝饶了我们。)
答案 1 :(得分:5)
您有两种方法可以回答您的问题:
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近似值。
答案 2 :(得分:1)
在-Xmx
标志的另一个question中,Runtime.getRuntime().maxMemory()
用于显示当前大小。还注意到-Xmx1024m
和-Xmx1g
导致相同的输出,表明数字是2的幂而不是10的幂。
请注意totalMemory()
和maxMemory()
之间的区别
What are Runtime.getRuntime().totalMemory() and freeMemory()?