Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.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堆_Java_Memory_Jvm_Heap Memory - Fatal编程技术网

内存管理和Java堆

内存管理和Java堆,java,memory,jvm,heap-memory,Java,Memory,Jvm,Heap Memory,在Java中,可以通过向JVM提供-Xmx参数来设置最大应用程序堆大小。假设是1GB。我认为1GB是从你启动应用程序的时候就给你的,所以应用程序可以在那个区域创建对象。但后来我读到了关于自适应大小调整技术的内容: 堆的大小、代数和存留空间在执行过程中可能会有所不同 JVM试图根据其策略找到最佳性能 还有调弦 现在,我迷路了。我不知道JVM默认情况下会调整堆大小。请您解释一下(或提供相关有用资源的链接)JVM在执行期间如何调整堆的大小?您设置的是允许JVM分配的最大堆大小。它通常以较小的大小开始,

在Java中,可以通过向JVM提供
-Xmx
参数来设置最大应用程序堆大小。假设是1GB。我认为1GB是从你启动应用程序的时候就给你的,所以应用程序可以在那个区域创建对象。但后来我读到了关于自适应大小调整技术的内容:

堆的大小、代数和存留空间在执行过程中可能会有所不同 JVM试图根据其策略找到最佳性能 还有调弦


现在,我迷路了。我不知道JVM默认情况下会调整堆大小。请您解释一下(或提供相关有用资源的链接)JVM在执行期间如何调整堆的大小?

您设置的是允许JVM分配的最大堆大小。它通常以较小的大小开始,并且只根据需要增长(即使在垃圾收集之后,仅仅重新使用现有内存是不够的),最近的JVM版本也会在适当的时候通过收缩堆来回馈操作系统空间(例如,在工作时间内的一段重负载结束后).

还值得注意的是,尽管JVM的大部分内存都在堆中,但也有许多其他本机数据结构和加载机制用于JVM本身的操作(JIT缓存空间、以字节码定义和加载的类等)。因此,即使您为JVM进程设置了1Gb的限制,它所占用的空间也会比操作系统上的限制少(或多)


值得注意的是,进程/mem列表中报告的内存也不会计算加载到多个进程共享的内存中的(本机)库,也不会计算已分配但进程尚未使用的虚拟内存。如果你想把所有这些都放进去,你可能需要设置
-XX:+AlwaysPreTouch

当然,重新调整大小只能发生在堆的“上限”(
-Xmx
)上,所以最大值仍然受到尊重。但是垃圾收集器可以使它变小,是的。它还可以从
-Xms
增长

通常,在某些情况下,您确实希望垃圾收集器重新调整堆的大小<例如,code>kubernetes就是这样一个环境。kubernetes没有交换,所以当你填满RAM时,豆荚就会开始被杀死。现在,如果您的吊舱设置为
-Xmx10g
,并且在某个时候它们确实使用了这么多,但目前仅使用
1GB
,对于kubernetes,它们仍然消耗
10GB
。更简单地说,有些pod现在不需要也不使用
9GB
,但java
GC
不会处理这些(更多详细信息)。这就是重新调整堆大小的方便之处

G1GC
始终可以将内存返回给操作系统(将大小重新调整为较小的堆),但在java-12之前,它很少这样做。例如,其他垃圾收集器算法(如
Shenandoah
)将更快地将内存返回操作系统

虽然这在某些情况下可能是一种优势,但它是有代价的<代码>取消提交页面(或调整大小)不是一个自由过程。然后,堆不仅用于分配新实例,还用于GC工作本身。当
G1
必须将活动对象复制到不同的区域时,它仍然使用堆空间从一个区域复制到另一个区域。还有一些内部的
GC
结构也可以使用堆,比如
SATB
队列等等


还有一个事实,因为GC工作中的某些步骤是并发的,所以在并发阶段进行时,您需要一个足够大的堆来覆盖该增量或新分配的对象。一般来说,堆越多(GC的喘息空间越大),应用程序的性能就越好。

小堆的另一个缺点是,每单位GC工作回收的垃圾量会更小。是的。更小的堆=更短但更频繁的GC。总的来说,哪一个更好取决于您的应用程序。这就是为什么他们给你这么多的选择来调整它。这不仅仅是垃圾收集的频率。这也是GC能够执行的有用工作的数量。。。消耗的每单位资源。对于一个拷贝收集器来说,“从”空间中的非垃圾要比垃圾处理更多的成本。如果堆太小,你实际上会失去两种方式。是的,还有其他维度和权衡考虑。例如,GC在多大程度上与CPU的有用工作竞争,或者是否经常需要停止世界暂停,以及这些暂停需要多长时间。总体而言,什么最有效取决于您的应用程序。这就是为什么他们给了这么多的选择来调整它。