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

OOM使用320 x 16MB Netty DirectByteBuffer对象杀死JVM

燕靖
2023-03-14

我运行一个应用程序在一个7.5GB RAM服务器(没有交换)与args:
-Xmx3g-Xms3g-Xlog: gc-XX: UseG1GC-XX: MaxGCPauseMillis=1000-XX: MaxDirectMemorysize=500m-XX: Metaspacesize=256m-XX: MaxMetaspacesize=256m-Dio.netty.maxDirectMemory=0-Djdk.nio.maxCachedBuffersize=104857

当堆90%为空时,进程的RSS不断增加,直到linux内存杀手采取行动。

获取堆转储:
选择db,db。容量,类别(边界内(db)。得到(0))。来自java的getName()。尼奥。DirectByteBuffer db,其中classof(边界内(db))。得到(0))。getName()。开始使用(“io.netty”)

它会产生320个容量==16MB的DirectByteBuffer实例,来自io.netty.buffer.PoolThreadCache$MemoryArea onCache$Entry

(我猜并非所有的“容量”都是物理分配的,因为它将超过5GB)

该应用程序没有直接使用Netty,但一些依赖项是:S3、Redisson和version-

如何控制使用的内存量?

共有2个答案

孙弘博
2023-03-14

Netty有几个java属性,您可以根据需要进行调整。

默认情况下,Netty在缓冲池分配器中使用直接内存分配。池分配器是强烈推荐的,因为它重用内存,无论直接与否。我建议不要更改默认的缓冲池分配器。

这里有一些属性需要在Java命令启动时设置:

>

  • -Dio。内蒂。noPreferDirect=true(默认为false):如果为true,将不使用池分配器的直接内存,而是使用堆内存;注意,它可能会慢一点,因为直接内存速度最快,您需要使用-Xms-Xmx

    -Dio。内蒂。maxDirectMemory=x(默认为-1):您可以更改此值

    • 如果

    例如,如果你能负担得起(而且最好)使用Netty的直接内存,但不超过1 GB,你可以设置:

    • -Dio。内蒂。maxDirectMemory=0

    如果不需要任何直接缓冲区,则可以设置:

    • -Dio.netty.noPreferDirect=true
    • -Dio.netty.maxDirectMemory=0

    结束但并非最不重要的一点是,除了先前的一项设置之外:

    • -XX: MaxDirectMemorysize=500m可能太小,如果使用直接内存,可能会增加这个-XX: MaxDirectMemorysize=1024m或更多
    • 你可以减少-Xmx3g-Xms3g-Xmx2g-Xms2g

  • 金高飞
    2023-03-14

    如果没有像您所做的那样导致OOM,您就无法控制内存量。Netty池不会表现得像JavaGC vs heap,即增加其工作的一些节流/频率,以便在指定的限制内使用资源(在特定情况下抛出OOM)。Netty内存池是为了模仿本机分配器(如jemalloc)的行为而构建的,因此它的目的是根据应用程序的工作需要保留尽可能多的内存。出于这个原因,保留的直接内存取决于应用程序代码执行的分配压力,即有多少未释放的alloc。

    相反,我建议接受它的本质,在preprod/测试机器上准备一个有趣的测试负载,并html" target="_blank">监控您感兴趣的应用程序的Netty直接内存使用情况。我想你已经配置了-Dio.netty.maxDirectMemory=0,目的是使用JMX来公开所使用的直接内存,但是Netty也可以公开它自己的指标(保存设置io.netty.maxDirectMemory),只需检查使用它的库注意通过JMX或使用任何度量框架进行公开。如果这些应用程序不公开它,则该API相当容易使用,请参阅https://netty.io/4.1/api/io/netty/buffer/PooledByteBufAllocatorMetric.html

     类似资料:
    • 问题内容: 我正在使用SUSE SLES 11在POWER7系统上运行多程序工作负载(基于SPEC CPU2006基准)。 有时,工作负载中的每个应用程序都会消耗大量内存,并且总内存占用量会超过系统中安装的可用内存(32 GB)。 我禁用了交换,因为否则使用交换的过程可能会严重影响测量结果。我知道通过这样做,内核可以通过OOM杀手来杀死某些进程。很好 问题是我希望内核杀死的线程以错误条件退出(例如

    • 问题内容: 当Linux内存不足(OOM)耗尽时,OOM杀手根据一些启发式方法选择一个要杀死的进程(这很有趣: http //lwn.net/Articles/317814/)。 如何以 编程方式 确定OOM杀手最近杀死了哪些进程? 问题答案: 试试看:

    • 错误: 内存不足,Java运行时环境无法继续。本机内存分配(mmap)无法映射71827456字节以提交保留内存。可能的原因:系统在32位模式下没有物理RAM或交换空间,遇到了进程大小限制。可能的解决方案:减少系统上的内存负载增加物理内存或交换空间检查交换备份存储是否已满在64位OS上使用64位Java减少Java堆大小(-xmx/-xms)减少Java线程数量减少Java线程堆栈大小(-xs)设

    • 问题内容: 我想知道如何“杀死”已启动的过程。我知道Process API,但是不确定,是否可以使用它来杀死已经运行的进程,例如firefox.exe等。如果可以使用Process API,可以请您指向正确的方向?如果没有,还有哪些其他可用选项?谢谢。 问题答案: 如果你从Java应用程序中以从头开始处理(例如,通过调用或),那么你将对其具有有效的引用,并且可以在Process类中调用该方法以终止

    • null 提前感谢你的帮助。最好的问候。 编辑:它是一个独立的嵌入式应用程序,没有服务器。这个问题发生在机器上部署的应用程序上(很难安装分析工具),但不会发生在我的开发PC上。