Java 32 位 Xmx 与 Java 64 位 Xmx
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21262911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java 32bit Xmx vs java 64bit Xmx
提问by user3219957
I am really confused with this.
Xmx according to the java docs, is the maximum allowable heap size.
Xms is the minimum required java heap size, and is allocated at JVM start.
On a 32 bit JVM (4GB ram), java -Xmx1536M HelloWorld gives a cannot allocate enough memory error.
On a 64 bit JVM (4GB Ram), java -Xmx20G HelloWorld works just fine. But I don't even have that much virtual or physical memory allocated.
So from this, I conclude that Java 32 bit is allocating the 1536M at JVM startup, but Java 64 bit is not.
Why? A simple Hello World should not need 1536M to run. I am just specifying that 1536M is the maximum, not that it is needed.
Explanations anyone?
我真的很困惑。
根据java docs,Xmx 是允许的最大堆大小。
Xms 是所需的最小 Java 堆大小,并在 JVM 启动时分配。
在 32 位 JVM(4GB ram)上,java -Xmx1536M HelloWorld 给出了无法分配足够的内存错误。
在 64 位 JVM(4GB Ram)上,java -Xmx20G HelloWorld 工作正常。但我什至没有分配那么多的虚拟或物理内存。
因此,我由此得出结论,Java 32 位在 JVM 启动时分配了 1536M,而 Java 64 位则没有。
为什么?一个简单的 Hello World 应该不需要 1536M 就可以运行。我只是指定 1536M 是最大值,而不是需要它。
任何人的解释?
回答by edubriguenti
Actually, the application is not allocating the Xmx memory at startup.
实际上,应用程序并没有在启动时分配 Xmx 内存。
The -Xms parameter configure the startup memory. (What are the Xms and Xmx parameters when starting JVMs?)
-Xms 参数配置启动内存。(启动 JVM 时的 Xms 和 Xmx 参数是什么?)
The 64bit environment allows a bigger memory allocation then 32bits. But, in fact, it's using the HD space, not the memory ram.
64 位环境允许比 32 位更大的内存分配。但是,实际上,它使用的是 HD 空间,而不是内存 ram。
See this other post for more info.
有关更多信息,请参阅此另一篇文章。
回答by Joshua McKinnon
There is a distinction between allocating the memory and allocating the address space. The Oracle JVM is allocating the address spaceon startup to ensure the heap is contiguous. This allows for certain optimizations to be used with the heap.
分配内存和分配地址空间是有区别的。Oracle JVM在启动时分配地址空间以确保堆是连续的。这允许对堆使用某些优化。
If the allocation fails, then Java won't start... as you have seen. It isn't necessarily using that much memory, but it is allocating the required address space up-front. Since you are passing -Xmx1536m
, it is saying ok, I need to allocate that in case you need it... and since it must be contiguous it does it up-front so it can guarantee it (or fails trying).
如果分配失败,那么 Java 将不会启动……正如您所见。它不一定使用那么多内存,但它会预先分配所需的地址空间。既然你正在通过-Xmx1536m
,那就是说好的,我需要分配它,以防你需要它......而且由于它必须是连续的,所以它可以预先进行,以便它可以保证它(或尝试失败)。
This behavior is the same on both 32-bit and 64-bit JVMs. What you are seeing is the 2GB per-process address space limitation of 32-bit processes (at least, on Windows this is the limitation - it may be slightly larger on other platforms) causing this allocation to fail on 32-bit, where 64-bit has no issues since it has much larger address space. But, you say, 1536m is less than 2GB, I should be good, right? Not quite - the heap is not the only thing being allocated in the address space, DLLs and other stuff is also allocated in the address space...so getting a contiguous 1536m chunk out of 2GB max on 32-bit is unfortunately very unlikely. I've seen values below 1000m fail on 32-bit processes with particularly bad fragmentation, and usually 1200-1300m is the max heap you can specify on 32-bit.
此行为在 32 位和 64 位 JVM 上相同。您看到的是 32 位进程的每个进程 2GB 地址空间限制(至少,在 Windows 上这是限制 - 在其他平台上可能稍大)导致此分配在 32 位上失败,其中 64 -bit 没有问题,因为它有更大的地址空间。但是,你说1536m不到2GB,我应该不错吧?不完全是 - 堆不是唯一在地址空间中分配的东西,DLL 和其他东西也在地址空间中分配......所以不幸的是,在 32 位上从最大 2GB 中获得一个连续的 1536m 块是非常不可能的。我已经看到低于 1000m 的值在 32 位进程上失败,碎片特别严重,通常 1200-1300m 是您可以在 32 位上指定的最大堆。
On modern OSes, ASLR(Address Space Layout Randomization) makes fragmentation of 32-bit process address space worse. It intentionally loads DLLs into random addresses for security reasons... making it even less likely you can get a big, contiguous heap in 32-bit.
在现代操作系统上,ASLR(地址空间布局随机化)使 32 位进程地址空间的碎片变得更糟。出于安全原因,它有意将 DLL 加载到随机地址中……使您获得 32 位大的连续堆的可能性更低。
In 64-bit, the address space is so large that fragmentation is no longer a problem and giant heaps can be allocated without issues. Even if you have 4GB of RAM on 32-bit, though, the 2GB per process address space limitation (at least on Windows) usually means the max heap is usually only 1300m or so.
在 64 位中,地址空间如此之大,以至于碎片不再是问题,并且可以毫无问题地分配巨型堆。即使你在 32 位上有 4GB 的 RAM,但是每个进程 2GB 的地址空间限制(至少在 Windows 上)通常意味着最大堆通常只有 1300m 左右。
回答by Сергей Морсин
Under Windows there is a difference in memory allocation operations with native WinAPI low-level functions like VirtualAlloc.
在 Windows 下,内存分配操作与 VirtualAlloc 等本机 WinAPI 低级函数存在差异。
"Reserving" means allocation of a continuous area within process' address space without actually making this area of virtual memory usable. Allocated area is not backed by actual physical RAM or swap space and does not consume any free memory. Any application can reserve any amount of address space limited only by processor's memory addressing capability (bitness).
“保留”意味着在进程的地址空间内分配一个连续的区域,而不实际使该虚拟内存区域可用。分配的区域不受实际物理 RAM 或交换空间的支持,并且不消耗任何可用内存。任何应用程序都可以保留仅受处理器内存寻址能力(位数)限制的任意数量的地址空间。
"Committing" means backing some of previously "reserved" memory with real memory - RAM or swap space, making it actually readable/writable by the process. This memory is taken from available OS virtual memory pool (RAM and swap).
“提交”意味着用真实内存(RAM 或交换空间)支持一些先前“保留”的内存,使其实际上可以被进程读取/写入。该内存取自可用的操作系统虚拟内存池(RAM 和交换)。
An alternative to "committing" memory (taking a blank page from the pool) is "mapping" a file into the previously "reserved" memory. This does not consume memory from the swap pool but uses the mapped file in a manner similar to a dedicated swap space for that specific region of a process' address space.
“提交”内存(从池中取出一个空白页)的替代方法是将文件“映射”到先前“保留”的内存中。这不会消耗交换池中的内存,而是以类似于进程地址空间的特定区域的专用交换空间的方式使用映射文件。
Native Windows applications (like JVM itself) reserve memory for all heaps needed in the future, but commit it only as needed. High-level memory operations like malloc() style functions or "new" operators really do "commits" as needed or even do their own heap management logic user-mode with memory committed ahead by large chunks as it is'a CPU-intensive kernel call and works at page (4k) granularity.
本机 Windows 应用程序(如 JVM 本身)为将来需要的所有堆保留内存,但仅在需要时提交。像 malloc() 风格的函数或“new”操作符这样的高级内存操作确实会根据需要进行“提交”,甚至在用户模式下使用大块提前提交的内存来执行自己的堆管理逻辑用户模式,因为它是一个 CPU 密集型内核以页面 (4k) 粒度调用和工作。
During process startup JVM "reserves" -Xmx memory, but "commits" only -Xms amount of it. The remaining reserved memory is committed on demand as heaps grow. So heaps can grow up to available memory or -Xmx parameter, whichever is smaller.
在进程启动期间,JVM “保留” -Xmx 内存,但“提交”仅 -Xms 数量。随着堆的增长,剩余的保留内存按需提交。所以堆可以增长到可用内存或 -Xmx 参数,以较小者为准。