当前位置: 首页 > 知识库问答 >
问题:

在 JVM 空闲时将内存释放回操作系统

云瑞
2023-03-14

我们有一个简单的微服务设置,基于Windows服务器上的Spring Boot和Java8。

许多服务的负载很低,因为它们是与各种外部合作伙伴的集成。所以它们很多时候都是空闲的。

问题在于,JVM 仅在触发垃圾回收时才会将内存释放回操作系统。因此,服务可能会开始使用32mb,然后为单个请求提供服务并分配2GB内存。如果该服务上没有其他活动,则不会受到 GC 和服务器上的其他服务的影响。

使用System.gc在外部或内部触发GC都可以,我已经弄清楚了如何使用< code >-XX:MaxHeapFreeRatio 和< code >-XX:minheafpreeratio 以及< code>-XX: UseG1GC来控制堆何时应该扩展并释放内存给操作系统。

我的问题是:当JVM空闲时,确保内存重新回到操作系统的最佳方法是什么?

一种想法是让服务监控自己,并在一段时间的空闲后触发一个System.gc,但这可能很棘手,也容易出错。所以希望有更好的建议。

您可以通过运行该程序的X个实例来复制。大约10个让我的8GB Windows机器放弃了。

import java.util.*;

public class Load {
  public static void main(String[] args) throws Exception {
    alloc();
    Scanner s = new Scanner(System.in);
    System.out.println("enter to gc ");
    s.nextLine();
    System.gc();
    System.out.println("enter to exit");
    s.nextLine();
  }

  private static void alloc() {
    ArrayList<String[]> strings = new ArrayList<>();
    int max = 1000000;
    for (int i = 0; i < max; i++) {
      strings.add(new String[500]);
    }
  }
}

<代码>c:\

编辑:这被标记为重复两次,但它不是链接问题的副本。第一个问题是同一问题的2010年版本,但这个问题是关于为什么GC不将内存释放回操作系统(这在当时是不可能的)。另一个问题是关于基本的GC设置,我已经写了我理解。我希望讨论如何在系统空闲时触发垃圾回收器。因此,每五秒钟运行一次 System.gc 是不可接受的,因为这会很有与有效请求发生冲突并破坏响应时间的风险。

共有1个答案

后凯捷
2023-03-14

如果调用System.gc()可以满足您的需求,我建议使用spring scheduler每隔x个月运行一次周期性任务。

这很容易实现,一些注释

@EnableAsync
@EnableScheduling
@Scheduled(cron = "...")

就是您所需要的。有关详细信息,请参阅Spring计划。

编辑

调用System.gc()仅仅给出了开始垃圾收集的建议,仍然由JVM来决定何时进行垃圾收集。

要找出您的系统是否空闲,您可以使用spring指标。有一些子类

org.springframework.boot.actuate.endpoint.PublicMetrics

像Tomcat公共指标或系统公共指标,为您提供有关系统的信息。您可以使用@Autowire注入它们,并调用 mertics() 来获取单个值。根据这一点,您可以决定您的系统是否处于空闲状态,

 类似资料:
  • 问题内容: 我对JVM内存管理(至少对于SUN的内存管理)有疑问。 我想知道如何控制JVM将未使用的内存发送回OS(以我的情况为Windows)的事实。 我编写了一个简单的Java程序来说明我的期望。使用- Dcom.sun.management.jmxremote选项运行它,以便例如也可以使用jconsole监视堆。 使用以下程序: 一旦第一个GC完成(预期),内部堆就释放了,但是内存仅从第三个

  • 在阅读了一些像这样的答案和JEP-346之后,我意识到G1确实会将内存释放回操作系统。 然而,它是否将内存释放回操作系统,即使当前内存使用可能低于初始堆内存(即在此JEP之前,在我的案例中为JDK11)? 假设我有一个Java11 VM,运行和设置为,在RAM上,但是我只消耗大约。G1会释放足够的内存回操作系统吗? 我在任何地方都没有找到任何文档说明G1仅限于在发布时考虑Xms阈值。 我在生产过程

  • 我正在为我的应用程序使用GC选项。 由于大多数人都已经体验过JVM擅长将堆增加到最大堆大小,但它不会将内存释放回操作系统。我遇到了

  • 我改进了代码,以便从垃圾收集器中获得更好的结果。 现在,当我调用时,它确实释放了所有内存。但是,当我在不调用 的情况下观察内存使用情况时,应用程序确实会保留并使用越来越多的内存。 这是否意味着我的改进正在起作用,我的所有引用都是正确的,我可以忽略JVM是如何自己释放内存的。或者,我的代码中是否存在其他问题,这些问题是JVM在不运行垃圾收集器的情况下保留更多内存的原因。

  • 问题内容: 我有一个应用程序对于某些进程暂时需要一定数量的内存/堆。如果可以选择给JVM一个最大堆大小的合理值,那么JVM将从一个小的堆开始,并按需向OS请求更多的内存。 我的问题是,当我的应用程序不再需要大量内存时,JVM是否会将额外的内存还给操作系统(例如,用于其他进程)。目前,即使不再需要,我的应用程序似乎也可以永久保留该内存。 问题答案: JVM确实将内存返回给操作系统,但是非常不情愿,因

  • 当垃圾收集器运行并释放内存时,内存会返回操作系统还是作为进程的一部分保留下来。我的强烈印象是,内存实际上从未释放回操作系统,而是作为内存区域/池的一部分保留下来,供同一进程重复使用。 因此,进程的实际内存永远不会减少。提醒我的一篇文章是这样的,Java的运行时是用C/C写的,所以我想同样的事情也适用? 更新< br >我的问题是关于Java的。我提到C/C是因为我假设Java的分配/释放是由JRE