如何让jvm及时充满gc

ux6nzvsh  于 7个月前  发布在  其他
关注(0)|答案(1)|浏览(93)

我们有一个Java应用程序,它消耗的内存不断增加。但是在执行jmap dump之后,内存使用量很快就会福尔斯降回开始时的水平。
我们已经使用了内存分析工具,但没有发现内存泄漏的嫌疑。然而,这种不断的增长将导致HPA不断扩大豆荚。
我想让JVM自动执行fullGC来回收所有内存。
我怎样才能让jvm及时执行完整的GC,这样使用的内存就不会堆积起来。
我们使用G1垃圾收集器和参数如下:

-Dio.netty.allocator.type=unpooled
-Xms100m
-Xmx1900m
-XX:StartFlightRecording=settings=default
-XX:+ShowCodeDetailsInExceptionMessages
-XX:MaxGCPauseMillis=1000
-XX:NewRatio=1
-XX:MaxRAMPercentage=75
-XX:+CrashOnOutOfMemoryError
-XX:+UseStringDeduplication
-XX:G1PeriodicGCInterval=60000
-XX:+UseG1GC
-XX:NativeMemoryTracking=summary
-Dio.netty.maxDirectMemory=0
-Dio.grpc.netty.shaded.io.netty.maxDirectMemory=0
u91tlkcl

u91tlkcl1#

我们有一个Java应用程序,它消耗的内存不断增加。
是的,这就是所谓的“记忆”使用。这是正常的-JVM就是为这种方式设计的。
如果系统中没有任何东西需要RAM,那么在需要RAM之前,实际上不需要释放它。如果JVM不尽快清理垃圾(实际上是释放垃圾),那么它们总共花费的CPU周期就更少。
JVM是一个小的计算机类概念:它从操作系统中获取一大块RAM,然后JVM自己管理这些内存--你的操作系统有一个内存系统(由mallocfree或类似的东西驱动),JVM有自己的内存系统,构建在上面(JVM只是mallocs一大块,然后使用垃圾收集来管理它)。
这不仅仅是“节省了少量的周期”;要实际将内存返回给操作系统,它需要返回一个连续的内存块,要做到这一点,JVM需要移动对象,这是昂贵的,并且需要锁定或至少CAS行为来管理多线程环境中的影响(并且由于GC在单独的线程上运行,如果这样更快,就GC而言,它总是一个多线程环境)。
因此,JVM不会进行GC,直到有很多东西需要GC处理。这会导致发生以下行为:JVM的内存使用量大致呈线性上升,直到达到某个阈值,然后在 * 非常 * 短的时间内急剧下降,然后重复这个过程。
考虑到这是正常的,“我如何使JVM像这样工作”实际上并不是您想要的-JVM并不是设计来以这种方式运行的。
我们已经使用了内存分析工具,但没有发现内存泄漏的嫌疑。然而,这种不断的增长将导致HPA不断扩大豆荚。
问题是,您的IAAS提供商“帮助”将成本放在malloc上。JVM是在这样的假设下运行的:如果操作系统允许您malloc新内存,而没有任何迹象表明这是有问题的,那么JVM将这样做,而不是过早地浪费周期GCing。
然而,你的IAAS实际上是让你malloc,但随后打电话给收银机来处理额外的负载。JVM使用的malloc调用没有任何功能:“你……确定?这会让你付出代价的!“所以JVM不知道它不应该。

**因此,在malloc运行新内存是有问题的环境中运行JVM时,由于它需要花费现金或必须从其他进程中窃取内存,您可以使用-Xmx -Xms来“锁定”JVM将使用多少堆,并完全避免malloc/free周期。

-Xmx设置了它声明的最大堆,而-Xms设置了最小堆。将其设置为相同的值,JVM将立即分配它需要的东西,并且之后再也不会为堆分配malloc/free。找到应用程序正常运行的内存,并选择这些数字。
这样做有一个缺点-您可能希望JVM扩展(从而增加您的成本),例如:更多的客户同时连接。不幸的是,JVM并不擅长这项工作。你不能告诉JVM:根据需要增长,但是,你知道,不要占用你不需要的内存。这是一个合理的想法,但是,JVM根本无法做到这一点,至少,如果你试图让它像那样工作,我所知道的JVM实现甚至都不能远程正常工作。
您的args列表中已经有了-Xmx1900m,所以您基本上已经在这样做了。如果这比你想支付的多,减少它。
请注意,-Xmx不是最后一个词:JVM还为每个活动线程分配1个堆栈,这些堆栈存在于堆之外;它是你传递给-Xss(它设置堆栈大小)的任何东西,乘以活动线程的最大数量;它位于-Xmx之上。除非创建线程的java代码显式地选择堆栈大小,在这种情况下,堆栈大小就是堆栈大小。请注意,许多早期的JVM都被窃听,并且会默默地忽略任何指定的堆栈大小,这些堆栈大小没有均匀地划分为某些操作系统强制的窗口大小。JVM还声明了一些更多的内存供自己使用,而不是堆。所以,如果你每月支付100美元购买2GB,但成本上升到400美元,如果你超过它,那么-Xmx1900m就太高了。如果您正在尝试优化,请考虑使用-Xss,看看在不遇到StackOverflowErrors的情况下可以将其降低到多低。

相关问题