在调查我们Java应用程序中的疑似内存泄漏时,我们发现大量内存被MySQL Connector创建的SSLSessionContextImpl
实例使用 - 每个连接一个实例。
SSLSessionContextImpl
实例都包含一个缓存,初始容量为(20480 / 0.75) + 1 = 27307
(请参见JDK-8210985和JDK源代码)。这个加上每半小时创建十个新连接的Hikari连接池(默认行为),意味着一周后我们有约1GB的死SSLSessionContextImpl
实例。这些实例在老年代内存池中,并被AbandonedConnectionCleanupThread
类幽灵引用,我们看到应用由于内存耗尽而死亡(在限制为1GB的Docker容器中),因此我的猜测是,在已经积累的实例上无法及时执行适当的GC。
从表面上看,似乎MySQL连接器的行为不太对,对于同一数据库服务器,它应该重复使用相同的SSLSessionContextImpl
- 毕竟, SSLSessionContext
接口的JavaDoc(它实现了该接口)说:
SSLSessionContext
表示与单个实体关联的一组SSLSessions
。例如,它可以与同时参与多个会话的服务器或客户端相关联。
这完美地描述了我们的情况!然而,连接器每次连接都会创建一个新的SSLSessionContext
。
因此,有两个问题:
- 为什么MySQL连接器不重复使用
SSLContext
?(当然,我们无法读取开发人员的想法 - 但是否有理由不想重复使用它?) - 我们是否可以通过某种方式使其重复使用
SSLContext
?