java - 没有足够的内存用于 Spring Boot(从 1Gb heroku dyno 开始)

标签 java spring spring-boot heroku jvm

我有一个Spring boot应用程序,一旦部署到heroku 512 Mb dyno。在某些时候,应用程序初始化在 JPA EntityManager 初始化时随机开始面临“Java 堆空间”错误。我已将内存增加至 1 Gb,将测功机切换至 Standard-1。指标已启用,我意识到,在大多数时间里,我的内存占用量为 512 Mb,甚至占用率还稍高。

enter image description here

所以,看起来 1 Gb 就足够了,就像之前它在 512 Mb 下成功工作一样。令人惊讶的是,我仍然在部署中获得随机成功:有时我会遇到 Java 堆空间错误,有时则不会。成功后,内存占用当然超过了512Mb,但明显小于1Gb。

Heroku 自己指定了 -Xmx,我无法配置它。

java $JAVA_OPTS -Xmx256m -jar target/*.jar --spring.profiles.active=prod,heroku,no-liquibase --server.port=$PORT

是启动应用程序的命令行。我可以将 $JAVA_OPTS 设置为 -Xmx900m,但它不会被拾取。 此外,它通过其自身形成 JAVA_TOOLS_OPTIONS,为 1Gb Standard-1 heroku dyno 设置有关 -Xmx671m 的内容。我也无法用我自己的更大的 -Xmx 覆盖这个值

我的问题有多个:

1) 我如何确定,在 Spring-Boot 启动时 JVM 已经使用了 -Xmx671m,而不是 -Xmx256m。一旦我尝试升级到 2 Gb dyno,但即使在它之下,我也遇到了 Java 堆空间错误,例如初始命令行调用的 -Xmx256m 仍然相同,即使对于 2Gb dyno 也是有意义的,而 -Xmx2Gb 设置当应用程序失败时,JAVA_TOOLS_OPTIONS 中的 for in 实际上并不影响启动的那部分。

2) 如果 JAVA_TOOLS_OPTIONS 中的 -Xmx 实际上有意义,那么 Spring Boot 应用程序如何在启动时尝试占用比稍后工作期间使用的堆更多的堆,以及它如何每次占用随机卷?是否可以调整此行为(例如,识别未使用的 bean 并排除它们;添加一些 JVM 选项等)

最佳答案

确认实际 Xmx 值的最佳方法是使用 heroku java:jconsole command或者使用像 heroku ps:exec 这样的命令,然后在进程上使用 jinfo

您还可以包含heroku-javaagent to log memory statistics或使用-XX:+PrintGC。这两个都会记录堆统计信息,您可以使用 heroku log --tail 查看它们。

我不确定我是否理解你问题的第二部分,但我怀疑你看到 JVM 使用了大量的堆外内存。有关发生这种情况的原因的更多信息,请参阅 this blog post on JVM memory categories .

关于java - 没有足够的内存用于 Spring Boot(从 1Gb heroku dyno 开始),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57997342/

相关文章:

java - Springboot 托管 GraphQL Server 不接受内容类型为 "application/json; charset=UTF-8"的查询

java - 有没有办法将 DatagramSocket 绑定(bind)到特定网卡上的任何端口,或者如果我指定网卡,我必须指定端口?

java - 扩展 File 类时出现 ClassCastException 问题

java - 获取同一 Controller 中不同方法的@RequestMapping值

java - 使用 spring,我可以提取静态方法的某些部分来用于设置 bean 的属性吗?

spring - Spring Boot中基于​​表达式的Autowire(使用Kotlin)

java - Spring 批处理 : conditional execution of steps

java - Java如何将TimeStamp直接转换成Seconds

java - 构建 Spring Boot 项目时出错

java - 如何从 Spring Boot 调用用户定义的 sql 函数?