Java堆内存保存大字节数组

我们的微服务应用程序使用 Java 8 Spring Boot 2。在本地运行负载测试注意到堆消耗内存但从未释放回来。我正在使用 G1 垃圾收集器运行应用程序,并且还从 JVisualVM 执行了手动 GC,但分配的内存仍然永远不会被释放。

我获取了堆转储并对其进行了分析,我可以清楚地看到系统类加载器创建的大字节数组被列为泄漏嫌疑对象。我看到字节数组实例保存了对端点“/test”的 HTTP 请求。但负载测试已经完成,线程回到运行负载测试之前的位置。

不知道为什么系统类加载器加载的字节数组包含所有这些元素并无缘无故地占用所有这些堆。

JVisualVM

泄密嫌疑人

字节数组

具有传出引用的对象

/test 端点是 @RestController 类中的唯一方法

@RequestMapping(value = "/test", method = RequestMethod.GET)

@CrossOrigin(origins = "*")

public void test() {

    logger.info("Testing1...");

}

以下是与服务器相关的Spring Boot application.properties:


server.port=8090

server.tomcat.max-threads=200

server.tomcat.accept-count=100

server.tomcat.min-spare-threads=20

server.error.whitelabel.enabled=false

server.max-http-header-size=2097152


qq_笑_17
浏览 64回答 2
2回答

Cats萌萌

Tomcat 缓存了许多对象以使其运行速度更快。通过设置,server.max-http-header-size=2097152您使这些缓存对象之一声明 2 MB 内存并保留它。该文档有以下内容processorCache:协议处理程序缓存处理器对象以提高性能。此设置指示缓存这些对象的数量。-1表示无限制,默认为200。如果不使用Servlet 3.0异步处理,一个好的默认值是使用与maxThreads设置相同的值。如果使用 Servlet 3.0 异步处理,一个好的默认值是使用 maxThreads 和最大预期并发请求数(同步和异步)中的较大者。所以我的建议是将设置server.max-http-header-size为更合理的值,例如8KB(默认值),并在测试表明您确实需要它时慢慢加倍(相关:当总标头大小大于时,Tomcat 抛出“400 Bad request” server.max-http-header-size)。

一只甜甜圈

在运行压力测试之前获取转储,并在运行压力测试之后获取转储。Eclipse MAT 允许您比较两个转储之间的直方图,以便您知道发生了内存泄漏。我建议使用 Java Mission Control (JMC) 来监视 JVM,您可以在其中仔细查看内存消耗(堆和非堆)。请注意正在使用的内存和已提交的内存之间的区别。较新版本的 Java 具有更复杂的算法,其中 JVM 将内存返回给操作系统。对于 Java 8,一种选择是使用 Eclipse Open J9 JVM。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java