即使Xms = Xmx,G1GC也会向操作系统释放内存吗? [英] Does G1GC release back memory to the OS even if Xms = Xmx?

查看:805
本文介绍了即使Xms = Xmx,G1GC也会向操作系统释放内存吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读了 this

After reading some answers like this and JEP-346, I have realised that the G1 does release memory back to the OS.

但是它会将内存释放回操作系统,甚至到当前内存使用可能降到初始堆内存以下(即,在此JEP之前,对于我而言为JDK11)吗?

However does it release memory back to the OS, even to the point that current memory use can drop below the initial heap memory (i.e before this JEP, in my case JDK11)?

假设我在8GB RAM上有一个运行Xms并且Xmx设置为5GB的Java 11 VM,但是我只在1GB上使用. G1会释放足够的内存回操作系统吗?

Assume I have a Java 11 VM running with Xms and Xmx set as 5GB, on a 8GB RAM, however I am consuming only around 1GB. Will G1 release enough memory back to the OS?

我在任何地方都找不到任何文档,说G1被限制在发布时要牢记Xms阈值.

I didn't find any documentation anywhere which says that the G1 is restricted to releasing keeping the Xms threshold in mind.

我在生产中观察到此情况,MemAvailable一直下降到一个点,然后在GC之后,它在8GB的盒子上跳升到接近30-35%.因此,我假设它正在释放内存,这就是MemAvailable正在回跳的原因.

I am observing this in Production, the MemAvailable keeps on decreasing till a point, and then after a GC, it jumps upto close to 30-35% on an 8GB box. So I am assuming it is releasing memory, which is why the MemAvailable is jumping back up.

将内存释放到OS到底是什么意思,它是在调用free/unmap吗?

Also what does it exactly mean to release memory to the OS, is it calling free/unmap ?

推荐答案

注意:我已经删除了先前的答案并研究了源(也建立了自己的JVM只是为了找出这一特定时刻),这是答案.

Note: I have deleted my previous answer and have studied the sources (also build my own JVM just to find out this particular moment), here is the answer.

简短答案

JVM 11 version(目前),使堆变小时,不会会低于Xms.

JVM 11 version (at the moment), will not go below Xms when making the heap smaller.

详细答案

绝对真理在源代码中.并且此处是决定是否缩小堆的决定.在下面的几行中,您可以看到,如果我们输入if,将出现一条日志语句:

The absolute truth is in the source code. And here is the decision taken to shrink the heap or not. A few lines below, you can see that if we enter that if, there will be a log statement:

尝试堆收缩(容量大于完全GC后的最大所需容量).

Attempt heap shrinking (capacity higher than max desired capacity after Full GC).

因此,从本质上讲,如果我们可以理解两个参数:capacity_after_gcmaximum_desired_capacity-我们可以解决这个难题.通常,capacity_after_gc并不容易掌握;主要是因为这取决于有多少垃圾以及当前GC可以回收多少垃圾.为简单起见,我将编写一些不会产生任何垃圾的代码,以便使该值恒定.

So in essence, if we can understand two parameters : capacity_after_gc and maximum_desired_capacity - we can solve this mystery. In general, capacity_after_gc is not something easy to grasp; mainly because it depends on how much garbage there was and how much the current GC could reclaim. For simplicity, I am going to write some code that does not generated any garbage, so that this value is constant.

在这种情况下,我们只需要了解maximum_desired_capacity.

In such a case, we only need to understand maximum_desired_capacity.

在上面的几行中,您可以看到这是通过以下方式计算的:

A few lines above, you can see that this is computed as :

maximum_desired_capacity =  MAX2(maximum_desired_capacity, min_heap_size);

不幸的是,这很棘手,因为要真正了解这些人机工程学是如何设置的,需要遵循并理解很多代码.尤其是因为它们取决于JVM开头的各种参数.

Unfortunately, this is where it gets tricky, because it's a lot of code to follow and understand to really see how these ergonomics are set; especially since they depend on various arguments that the JVM has been started with.

例如min_heap_size

// If the minimum heap size has not been set (via -Xms),
// synchronize with InitialHeapSize to avoid errors with the default value.

注意,他们甚至将-Xms称为 minimum ;尽管文档说它是 initial .您还可以注意到,它进一步取决于另外两个属性:

Notice, that they even refer to -Xms as minimum; though the documentation says it's initial. You can also notice that it further depends on another two properties :

 reasonable_minimum , InitialHeapSize

这将很难进一步解释;这就是为什么我不会的原因.相反,我将向您展示一些简单的证明(我确实完成了大部分代码...)

This will be difficult to explain further; that is why I will not. Instead, I will show you some simple proof (I did go through the majority of that code...)

假设您有以下非常简单的代码:

Suppose you have this very simple code:

public class HeapShrinkExpand {

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 10; i++) {
            Thread.sleep(500);
            System.gc();
        }
    }
}

然后运行:

-Xmx22g 
-XX:InitialHeapSize=1g
"-Xlog:heap*=debug" 
"-Xlog:gc*=debug" 
"-Xlog:ergo*=debug" 

在日志中,我会看到:

[0.718s][debug][gc,ergo,heap   ] GC(0) Attempt heap shrinking (capacity higher than max desired capacity after Full GC). Capacity: 1073741824B occupancy: 8388608B live: 1018816B maximum_desired_capacity: 27962026B (70 %)
[0.719s][debug][gc,ergo,heap   ] GC(0) Shrink the heap. requested shrinking amount: 1045779798B aligned shrinking amount: 1044381696B attempted shrinking amount: 1044381696B

这告诉您一些统计信息,这些数据是关于需要减少多少,当前容量是多少等.下一行将向您显示实际上堆减少了多少:

This tells you some stats around how much shrinking is desired, what is the current capacity, etc. The next line will show you how much the heap has gone down, actually:

[0.736s][debug][gc,ihop] GC(0) Target occupancy update: old: 1073741824B, new: 29360128B

堆确实收缩了,下降到29MB左右.

The heap did shrink, down to around 29MB.

如果我添加一个JVM启动标志:-Xms10g,则那些GC日志负责显示堆收缩到多少.将不再存在.

If I add a single JVM start-up flag: -Xms10g, those GC logs that are responsible for showing how much the heap was shrank to; will not be present anymore.

实际上,如果我运行自己的JMV(启用了一些日志记录),则这两个值:capacity_after_gcmaximum_desired_capacity将会始终保持相同的值;这意味着将永远不会输入if statement,并且堆也永远不会低于-Xms.

And in fact if I run my own JMV (with some logging enabled), those two values: capacity_after_gc and maximum_desired_capacity will always have the same values; meaning that if statement will never be entered and heap will never go below -Xms.

我已经用JDK-13运行了相同的代码,尽管那里有缩小的日志(当将-Xms作为参数时),但基础堆仍停留在-Xms处.我发现更有趣的是在java-13下尝试运行:

I have run the same code with JDK-13 and, while the shrinking logs are present there (when -Xms is given as an argument), the underlying heap stays at the -Xms, still. What I find even more interesting is that under java-13, trying to run with:

 -Xmx22g -Xms5g -XX:InitialHeapSize=1g

将正确地显示以下错误:

will correctly error out with:

指定的最小和初始堆大小不兼容

Incompatible minimum and initial heap sizes specified

这篇关于即使Xms = Xmx,G1GC也会向操作系统释放内存吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆