Glassfish Server 5.0运行2-3小时堆内存泄漏原因咨询
问题原因分析与解决方案
从你的堆转储信息来看,这个内存溢出问题的核心是ALPN(应用层协议协商)相关的内存泄漏,具体原因可以拆解为以下几点:
- Grizzly版本的固有Bug:GlassFish 5.0默认搭载的Grizzly框架(2.3.x系列)存在ALPN协商器(
ALPNServerNegotiator)未正确释放SSLEngineImpl实例的缺陷。当服务器处理大量HTTPS连接时,这些SSLEngine实例会被NegotiationSupport类持有的引用一直保留,无法被垃圾回收(GC),最终导致堆内存被占满。 - NPN与ALPN的兼容冲突:GlassFish 5.0同时支持旧版的NPN(Next Protocol Negotiation)和标准的ALPN协议用于HTTP/2协商,两者的协商逻辑在处理
SSLEngine时可能存在交叉引用泄漏,尤其是在混合处理HTTP/1.1和HTTP/2请求的场景下,SSLEngineImpl实例被缓存后无法被正确清理。 - SSLEngine资源未正确释放:如果服务器的连接生命周期管理存在问题,或者应用自定义了SSL处理逻辑但未正确调用
SSLEngine.closeOutbound()/closeInbound()方法,会导致SSLEngineImpl及其关联的缓冲区、会话数据长期占用内存,无法被回收。
可行的解决方案
针对这个问题,你可以按优先级尝试以下方案:
升级Grizzly框架版本
这是最根本的解决方法。Grizzly在2.3.35及以上版本修复了ALPN相关的内存泄漏问题。你需要替换GlassFish安装目录下glassfish/modules/路径中的所有grizzly-*.jar文件为对应版本的jar包,重启服务器后即可解决泄漏问题。禁用不必要的ALPN/NPN支持
如果你不需要使用HTTP/2协议,可以直接关闭ALPN支持来避免泄漏:- 编辑GlassFish的域配置文件
domain.xml,找到HTTPS对应的<network-listener>节点,添加enable-alpn="false"属性; - 或者在JVM启动参数中添加
-Djdk.tls.alpn.enabled=false,全局禁用ALPN协议。
- 编辑GlassFish的域配置文件
临时调整GC参数缓解问题
如果暂时无法升级框架,可以通过增大堆内存(比如设置-Xmx4g)并启用G1GC垃圾收集器(添加-XX:+UseG1GC)来延迟内存溢出的时间,但这只是临时缓解,无法根治泄漏。检查自定义SSL逻辑
如果你的应用有自定义的SSLEngine工厂或SSL上下文配置,确保在使用完SSLEngine实例后,正确调用关闭方法释放资源,避免持有不必要的引用。
内容的提问来源于stack exchange,提问作者chanuka
相关产品推荐
相关产品推荐

