Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java堆分配是2MB的倍数_Java_Heap_Heap Memory - Fatal编程技术网

Java堆分配是2MB的倍数

Java堆分配是2MB的倍数,java,heap,heap-memory,Java,Heap,Heap Memory,我注意到Java堆分配是2 MB的倍数。例如,我启动JVM时使用的-Xmx值为1021m、1022m这两个JVM的堆大小均为1022m。类似地,堆大小1023m,1024m从1024m开始 结果如下: C:\Users\myuser>java -Xmx1021m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize" uintx MaxHeapSize := 1071644

我注意到Java堆分配是2 MB的倍数。例如,我启动JVM时使用的
-Xmx值为1021m、1022m
这两个JVM的堆大小均为
1022m
。类似地,堆大小
1023m,1024m
1024m
开始

结果如下:

C:\Users\myuser>java -Xmx1021m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize"
    uintx MaxHeapSize                              := 1071644672
          {product}
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode)

C:\Users\myuser>java -Xmx1022m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize"
    uintx MaxHeapSize                              := 1071644672
          {product}
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode)
在这两种情况下,它将MaxHeapSize显示为1071644672字节,即1022mb

C:\Users\myuser>java -Xmx1023m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize"
    uintx MaxHeapSize                              := 1073741824
          {product}
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode)

C:\Users\myuser>java -Xmx1024m -XX:+PrintFlagsFinal -version | findstr "MaxHeapSize"
    uintx MaxHeapSize                              := 1073741824
          {product}
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) Client VM (build 25.121-b13, mixed mode)
在这两种情况下,它将MaxHeapSize显示为1073741824字节,即1024mb

这种行为与Xms类似

问题1:为什么堆大小从指定值更改为2的下一个倍数

问题2:为什么Java甚至没有在JVM实际启动时使用与指定值不同的值来警告我们

问题3:是否有一个标志或某种方式强制JVM创建1021mb的堆


问题4:在假设的情况下,假设我的机器上有1023mb的可用内存,我尝试创建一个具有1023mb堆的JVM。通过上述行为,它实际上尝试从1024mb开始,这是不可用的。JVM创建会失败吗?

您观察到的是操作系统施加的限制,而不是JVM。 当为进程分配内存时,操作系统通常不操作字节(因为这样做会使分配,尤其是对内存的访问成为一个非常缓慢的过程)——它们使用所谓的“内存页”。你可以从开始阅读更多关于它的内容

因此,您的操作系统似乎有2MB的内存页大小,这意味着当进程请求为自己分配一些内存时,它至少可以得到2MB,这正是您的情况下发生的情况


对于问题的第二部分,您确实可以通过更改操作系统的内存页大小(有些JVM确实有此选项),强制JVM拥有不是2MB倍数的堆。但是,这可能会产生不可预见的后果,因为它会影响该操作系统内运行的所有进程。

这实际上非常有趣。因此,CPU同时支持两种页面大小,如下所述

4KB
是常用的;另外两个被称为
大页面

看看这个,您会发现一个可能的页面大小是
2MB
,您可以说-问题解决了

因为你知道,你的内存确实是按照你的例子中2MB的块对齐的。这实际上是我读到你的问题时的第一反应。但后来我决定试试我的MAC电脑。现在我使用的cpu是x86,它显然支持所有3种页面大小:4KB、2MB、1GB

Mac操作系统本身呢?我在
热点/src/os/bsd/vm/os_bsd.cpp中找到了页面大小实际读取值的来源(jdk-9)。实际代码是:

   Bsd::set_page_size(getpagesize())
我使用了这个简单的函数
getpagesize
,并在Xcode中运行它。惊喜,惊喜!它只有
4KB
,但堆仍然像示例中那样对齐(按
MB
大小)

然后我记得这里有一个页面大小的对齐:
share/vm/memory/heap.cpp
。以下是实际的方法:

 static size_t align_to_page_size(size_t size) {
     const size_t alignment = (size_t)os::vm_page_size();
     assert(is_power_of_2(alignment), "no kidding ???");
     return (size + alignment - 1) & ~(alignment - 1);
 }
这将使内存增长一点,这样它就可以被页面大小整除(在我的例子中是
4KB
);这正是您在评论中所说的被
4KB
整除

现在为了理解下一个,我做了很多搜索<代码>jdk-9-sources | grep Xmx
我很幸运!我发现的幸运点如下:
share/vm/gc/shared/collectorPolicy.cpp
还有一条很棒的评论:

 size_t CollectorPolicy::compute_heap_alignment() {
     // The card marking array and the offset arrays for old generations are
     // committed in os pages as well. Make sure they are entirely full (to
     // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
     // byte entry and the os page size is 4096, the maximum heap size should
     // be 512*4096 = 2MB aligned.

     size_t alignment = CardTableRS::ct_max_alignment_constraint();

     if (UseLargePages) {
         // In presence of large pages we have to make sure that our
         // alignment is large page aware.
         alignment = lcm(os::large_page_size(), alignment);
     }

     return alignment;
 }

在这一点上,我不太确定这是否是使堆在
2MB
上对齐的唯一方法。这种不确定性来自这样一个事实,即该文件中满是关于如何增加堆以调整某些参数的注释。理解所有这些细节会很有趣,但非常耗时,所以我放弃了

我想这是操作系统而不是JVM的一个限制:操作系统通常有“内存页”的概念——分配给进程的最小物理内存量。每个进程可以有多个页面,但不少于一个页面。您的操作系统恰好有2MB的页面大小。@M.Prokhorov您的评论几乎是正确的,唯一的更正是最小的虚拟内存量。更简单的说,内存页-虚拟,内存帧-物理。@Eugene我如何在windows和linux上获得进程可能的最小虚拟内存量?@Arun你是说我如何找到windows和linux页面大小的最小值?你应该把问题说清楚一点,因为我不明白,但可能只有我…@Arun也。。对于你的问题(我希望尽快给出答案),你能指定你在什么操作系统上运行这个吗?不幸的是,不是这样。我在我的mac上运行了它,页面大小为
4KB
。我甚至查看了关于如何在BSD上计算页面大小的jdk-9源代码:
BSD::set_page_size(getpagesize())在hotspot/src/os/bsd/vm/os_bsd.cpp中。运行
getpagesize()
返回4KB,因此这还有更多…@Eugene,如果我们查看热点源,那么在
Universe.cpp
中有一个
首选的\u heap\u base()
。我没有太多的运气去理解它到底做了什么,因为有这么多的变量被移动(我在这方面还远远不是专家),但似乎大小一致,这可能解释了我们正在处理的这种行为。我想我在这里发现了问题。。。并提交答案。