Mongo Java Connection导致内存泄漏

Amz*_*Amz 9 java memory-leaks mongodb

我正在以下面的方式构建MongoClient Connection:

public static synchronized MongoClient getInstance(String mongoDbUri) {
        try {
            // Standard URI format: mongodb://[dbuser:dbpassword@]host:port/dbname
            if( mongoClient == null ){
                mongoClient = new MongoClient(
                              new MongoClientURI(mongoDbUri));
            }
        } catch (Exception e) {
            log.error(
                    "Error mongo connection : ",
                    e.getCause());
        }
        return mongoClient;
    }
Run Code Online (Sandbox Code Playgroud)

在多个事务运行的一段时间内,我看到一些内存耗尽了应用程序,而这些内存未被释放.

分析时,堆转储看到该类的内存消耗最大

com.mongodb.internal.connection.PowerOfTwoBufferPool

mongo客户端正在尝试连接到mongos实例.该应用程序在3个分片上有3个副本集,还有一个用于保存元数据的配置服务器.

为了向它添加更多细节,我有一个用@ Component注释的spring托管bean.有一个带@PostConstruct的注释用于调用上述方法的bean.在spring类中我们正在使用insert/update/create Mongo客户端.

谢谢.

Att*_*ila 2

PowerOfTwoBufferPool实际上是一个缓存,因此乍一看这可能看起来像是内存泄漏

\n

mongodb -user 组回复包含详细信息:

\n
\n

PowerOfTwoBufferPool...由于是缓存,因此\n此行为是预期的。因此\n可能看起来像是泄漏。

\n

简而言之,它PowerOfTwoBufferPool拥有许多 ByteBuffer 实例池,每个池包含一组大小相等的缓冲区。最小大小为 1K,最大大小为 16MB,从 1K 到 16MB 以两倍大小递增。每个相同大小的缓冲区池的大小不受限制,由应用程序的使用情况决定。一旦缓冲区被缓存在池中,它就会保持池化状态(或正在使用中),直到 MongoClient 关闭为止。因此,它\xe2\x80\x99s\n完全期望在 JVM 状态自省期间,池的内容\n将显示为泄漏嫌疑对象,就像任何缓存一样。

\n

PowerOfTwoBufferPool存在是为了减少 GC 负载。\xe2\x80\x99s\n众所周知,JVM 中的现代垃圾收集器对大型分配的处理方式与较小的分配不同,因此,如果应用程序\n不对大型对象(如这些缓冲区)进行任何池化,\n它将具有增加 GC 负载的影响,因为垃圾收集器必须比收集较小的对象做更多的工作来收集这些大对象。这样做的代价是驱动程序保留了可由应用程序其他部分使用的内存。特别是,它拥有足够的内存来处理应用程序迄今为止看到的最大峰值负载。

\n
\n