首页 > 解决方案 > GAE 使用的内存比我的 Java 应用程序多得多

问题描述

我有一个在 Google App Engine 上运行的 Java 应用程序(Spring Boot);但是,我发现我的 Java 应用程序内存消耗与 GAE 显示的仪表板之间存在奇怪的差异。

在我使用 VisualVM 的本地机器中,我可以看到即使在高峰时间它也不会消耗超过 100MB,我添加了一个 servlet 来返回使用的内存量:

@GetMapping("/")
public String index() {
  Runtime rt = Runtime.getRuntime();
  long total = rt.totalMemory();
  long free = rt.freeMemory();
  long used = total - free;
  return "Total: " + total / 1024 / 1024 + "MB<br>Used: " + used / 1024 / 1024 + "MB<br>Free: " + free / 1024 / 1024 + "MB";
}

我在 GAE 中部署的应用程序现在返回:

Total: 91MB
Used: 69MB
Free: 21MB

同时,GAE 仪表板显示它正在消耗大约 350MB 内存仪表板 IMG url

为什么会这样?它迫使我使用 F2 实例;如果我降级到 F1,它会一直失败并重新启动。

我注意到,一旦我将我的 cronjob 从每 30 分钟运行一次更改为每 2 分钟运行一次,他们开始在前端实例中每天向我收取 40 小时的费用,大约是在此更改之前 16 小时,而我只有 1 个实例正在运行。这怎么可能? 实例计数 img url

谢谢

标签: javaspring-bootgoogle-app-enginegoogle-cloud-platform

解决方案


您看到这些差异的原因是 Cloud Console 显示了 JVM 进程的实际大小(包括堆栈帧、永久生成空间、直接缓冲区、机器代码等),其中适用于实例的内存限制是指JVM 堆。运行时使用一些堆内存,这些内存会计入应用程序的总堆使用量。

现在,重要的是要了解这些方法的作用以及如何计算要分配的可用内存:

总内存()

JVM 当前使用的所有内存。它通常低于 maxMemory,因为 JVM 会延迟分配内存,“延迟”意味着最初分配并使用了一些内存,如果需要新的内存块,则会完成另一次分配,直至所有可用内存 ( maxMemory())。


最大内存():

最大可用堆内存(实例大小限于此值)。


空闲内存():

当前由 JVM 分配但未使用的内存部分。


可以分配的“实际总内存”为:

rt.freeMemory() + (rt.maxMemory() - rt.totalMemory())

所以可以有比输出更多的可用内存rt.freeMemory()


推荐阅读