【问题标题】:Java Heap Memory Holding Large byte Array保存大字节数组的 Java 堆内存
【发布时间】:2020-02-13 15:58:18
【问题描述】:

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

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

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

JVisualVM

Leak Suspects

byte Array

Objects with Outgoing Ref

/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

【问题讨论】:

  • 你能发布实现/测试端点吗?
  • @maitreyak 我已经发布了只是一个班轮的方法
  • 你有多少个 http 工作线程?我怀疑网络服务器为每个线程预先分配了 IO 缓冲区。
  • @radai 我也发布了我的服务器属性。我有最小 20 和最大 200
  • 如果你把它固定在 1 个线程上,数字会改变吗?

标签: java spring-boot java-8 heap-memory


【解决方案1】:

Tomcat 缓存了许多对象以使其运行得更快。使用设置server.max-http-header-size=2097152,您可以让其中一个缓存对象占用 2 MB 内存并保留它。在这种情况下,它是Http11OutputBuffer,您可以看到here 它声称(在您的情况下)2 MB 内存。 Http11OutputBufferHttp11Processor 使用,您可以看到here

documentationprocessorCache 有以下说法:

协议处理程序缓存处理器对象以提高性能。此设置决定了这些对象中有多少被缓存。 -1 表示无限制,默认为 200。如果不使用 Servlet 3.0 异步处理,一个好的默认值是使用与 maxThreads 设置相同的值。如果使用 Servlet 3.0 异步处理,一个好的默认值是使用 maxThreads 和预期并发请求的最大数量(同步和异步)中的较大者。

所以我的建议是将server.max-http-header-size 设置为更合理的值,例如8KB(默认值)并慢慢翻倍,当测试表明您确实需要它时(related:当总标头大小大于 server.max-http-header-size 时,Tomcat 抛出“400 Bad request”)。

【讨论】:

  • @TZ-EZ AFAIK 它没有,但也许文档对此有话要说?当需要处理大量请求的尖峰时,清除缓存也会增加负载 - 这与您在尖峰期间想要的相反,而填充的缓存可以防止这种情况。
【解决方案2】:

在运行压力测试之前获取一个转储,在运行之后获取一个转储。 Eclipse MAT 允许您比较两个转储之间的直方图,因此您会知道发生了内存泄漏。

我建议使用 Java Mission Control (JMC) 来监控 JVM,您可以在其中仔细查看内存消耗(堆而不是堆)。注意正在使用的内存和已提交的内存之间的区别。

较新版本的 Java 具有更复杂的算法,其中 JVM 将内存返回给操作系统。对于 Java 8,一种选择是使用 Eclipse Open J9 JVM。

推荐阅读:

https://openjdk.java.net/jeps/346

https://jelastic.com/blog/elastic-jvm-vertical-scaling/

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2010-09-18
  • 2012-04-20
  • 2016-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
  • 2011-07-23
相关资源
最近更新 更多