Spring boot 当JVM空闲时将内存释放回操作系统
我们有一个简单的微服务设置,基于SpringBoot和Windows服务器上的Java8 许多服务的负载较低,因为它们是各种外部合作伙伴的集成。所以他们大部分时间都是空闲的 问题是JVM只在触发垃圾收集时将内存释放回操作系统。因此,一个服务可能开始使用32mb,然后服务一个请求并分配2GB内存。如果该服务上没有其他活动,它将不会执行GC,服务器上的其他服务将受到影响 使用System.GC从外部或内部触发GC。GC工作正常,我已经知道如何使用Spring boot 当JVM空闲时将内存释放回操作系统,spring-boot,garbage-collection,jvm,java-8,g1gc,Spring Boot,Garbage Collection,Jvm,Java 8,G1gc,我们有一个简单的微服务设置,基于SpringBoot和Windows服务器上的Java8 许多服务的负载较低,因为它们是各种外部合作伙伴的集成。所以他们大部分时间都是空闲的 问题是JVM只在触发垃圾收集时将内存释放回操作系统。因此,一个服务可能开始使用32mb,然后服务一个请求并分配2GB内存。如果该服务上没有其他活动,它将不会执行GC,服务器上的其他服务将受到影响 使用System.GC从外部或内部触发GC。GC工作正常,我已经知道如何使用-XX:MaxHeapFreeRatio和-XX:Mi
-XX:MaxHeapFreeRatio
和-XX:MinHeapFreeRatio
与-XX:+UseG1GC
控制堆何时应该扩展并释放内存到操作系统
我的问题是:当JVM空闲时,什么是确保将内存释放回操作系统的最佳方法?
一个想法是让服务监视器本身在空闲一段时间后触发System.gc EFT,但这可能会很棘手且容易出错。希望能有更好的建议
您可以通过运行该程序的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]);
}
}
}
import java.util.*;
公共类负载{
公共静态void main(字符串[]args)引发异常{
alloc();
扫描仪s=新的扫描仪(System.in);
System.out.println(“进入gc”);
s、 nextLine();
gc();
System.out.println(“进入到退出”);
s、 nextLine();
}
私有静态void alloc(){
ArrayList字符串=新的ArrayList();
int max=1000000;
对于(int i=0;i
c:\>java-server-XX:+UseG1GC-Xms32m-Xmx2048m加载
编辑:这被标记为重复两次,但它不是链接问题的重复。第一个问题是2010年版本的同一个问题,但这个问题是关于为什么GC不将内存释放回操作系统(这在当时是不可能的)。另一个问题是关于基本的GC设置,我已经写过,我理解。我希望讨论在系统空闲时如何触发垃圾收集器。因此,每五秒钟运行一次System.gc是不可接受的,因为这样会有与有效请求发生冲突并破坏响应时间的高风险 如果调用System.gc()满足您的需要,我建议使用spring scheduler每隔x个月运行一次定期任务
这很容易实现,有些注释
@EnableAsync
@EnableScheduling
@Scheduled(cron = "...")
这就是你所需要的。
有关详细信息,请参阅
编辑
调用System.gc()只给出启动垃圾收集的建议,何时启动还是由JVM决定
要了解系统是否空闲,可以使用spring度量。
有一些子类
org.springframework.boot.actuate.endpoint.PublicMetrics
例如TomcatPublicMetrics或SystemPublicMetrics,它们为您提供有关系统的信息。
您可以使用@Autowire将它们注入,并调用mertics()来获取单个值。根据这一点,您可以决定系统是否空闲,这可能是的重复,调用“system.gc()”也不能保证在该点启动gc,请参阅我的问题不是该问题的重复。我了解GC的基本机制以及堆是如何返回给操作系统的。我也理解System.gc没有任何保证,尽管我还没有看到它忽略请求。我想讨论一下在系统空闲时如何最好地调用显式垃圾收集。抱歉,我似乎错过了你文章的真正要点“我的问题是:当JVM空闲时,确保将内存释放回操作系统的最佳方法是什么?”编辑后的问题以粗体显示;-)@拉塞尔:对不起,我错过了这个微妙之处。我重新开始了这个问题。嗯,是的。我只是在想那些台词。但我也认为,这样的解决方案也会在系统不空闲时触发不必要的垃圾收集。例如,在一个请求中触发一个完整的堆GC很可能会由于计划不佳的GC引起的很多长反应而毁掉了我的SLA。接受这个答案。感觉就像是一个黑客。我更喜欢一些外部解决方案,比如一个聪明的JVM标志或其他东西。