NewRelic Agent 9.1.0在Tomcat 10.1中引发内存泄漏问题咨询
New Relic Agent 9.1.0 重部署Web应用时的内存泄漏与非法访问问题
我们使用最新版New Relic Agent 9.1.0,在重新部署Web应用时发现内存泄漏问题。最初的警告日志如下:
07-Apr-2026 08:33:34.983 WARNING [http-1557107106] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [prod] appears to have started a thread named [New Relic Token Expiration Handler] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.base@17.0.18/jdk.internal.misc.Unsafe.park(Native Method) java.base@17.0.18/java.util.concurrent.locks.LockSupport.park(LockSupport.java:341) java.base@17.0.18/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(AbstractQueuedSynchronizer.java:506) java.base@17.0.18/java.util.concurrent.ForkJoinPool.unmanagedBlock(ForkJoinPool.java:3465) java.base@17.0.18/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3436) java.base@17.0.18/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1630) java.base@17.0.18/java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:435) java.base@17.0.18/java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1062) java.base@17.0.18/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1122) java.base@17.0.18/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) java.base@17.0.18/java.lang.Thread.run(Thread.java:840)
随后持续出现非法访问日志:
08-Apr-2026 00:22:38.904 INFO [Thread-15843] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [org/apache/http/client/entity/DeflateInputStream.class]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access. java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [org/apache/http/client/entity/DeflateInputStream.class]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access. at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1396) at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:984) at com.newrelic.agent.util.asm.Utils.getClassResource(Utils.java:147) at com.newrelic.agent.util.asm.Utils.readClass(Utils.java:99) at com.newrelic.agent.instrumentation.context.InstrumentationContextClassMatcherHelper.isMatch(InstrumentationContextClassMatcherHelper.java:44) at com.newrelic.agent.instrumentation.context.ClassesMatcher$1.run(ClassesMatcher.java:55) at java.base/java.lang.Thread.run(Thread.java:840)
观察到New Relic保留了已停止的旧Web应用实例,尝试访问时触发插桩错误。以下是无需禁用New Relic的解决办法:
解决办法
1. 配置Agent的类加载隔离
修改newrelic.yml配置文件,启用类加载隔离设置,避免Agent线程持有Web应用类加载器的引用:
class_transformer: class_loader_isolation: true
该设置让Agent使用独立类加载器处理插桩逻辑,减少与Web应用类加载器的耦合,避免应用停止后Agent线程仍持有旧类加载器引用。
2. 手动触发Agent线程清理
在Web应用的停止钩子中调用New Relic的清理API,确保Agent线程被正确终止:
import com.newrelic.api.agent.NewRelic; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class NewRelicCleanupListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent sce) { NewRelic.shutdown(); } }
在web.xml中注册该监听器:
<listener> <listener-class>com.yourpackage.NewRelicCleanupListener</listener-class> </listener>
此操作会触发Agent关闭流程,终止所有后台线程,释放对旧应用实例的引用。
3. 调整Tomcat线程清理策略
修改Tomcat的context.xml,启用强制线程清理:
<Context> <Loader clearReferencesThreads="true" clearReferencesStopThreads="true" /> </Context>
clearReferencesStopThreads参数会让Tomcat在应用停止时强制终止未正确停止的线程,包括New Relic后台线程,避免内存泄漏。
4. 跟进Agent版本更新
尽管当前使用9.1.0版本,仍可能存在未修复的线程泄漏bug,持续关注官方更新日志,一旦有对应修复版本发布,立即升级。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

