我目前有四个不同的 java 应用程序,它们由 .bat 文件启动的 jar 运行,这些文件位于 Windows XP Embedded 开始菜单的 starup 文件夹中。我还启动了 Firefox。现在 Firefox 或其中一个 Java 应用程序刚刚关闭。估计我内存不足(Win XP Embedded with 512 MB RAM)。
这四个 Java 应用程序是,
- HMI 后端(使用 Spark“微”框架构建)
- 一个记录器应用程序,可将来自 PLC 的数据记录到 H2 数据库中。这通过使用 Timer/Timertask
- h2 数据库服务器
- 执行周期性作业的调度程序。这是通过使用 Quartz。
因此,这些 Java 应用程序中的每一个都在它们自己的 JVM 中启动(据我所知)。第一个问题是:我能否通过在一个 JVM 而不是四个 JVM 中运行这四个应用程序来降低它们的内存使用量。如果是这样,我应该使用它来启动每个应用程序吗?
除此之外,我应该做的第一件基本事情是什么来降低内存占用,因为我对“真正的”Java 编程还很陌生。 H2连接池,重用对象还有什么? Jconsole 和那个 Xmx 东西?
可能很天真,但我真的认为,嘿,GC 会为我处理“一切”。可能不会? =)
编辑: HMI 后端使用 Jetty 网络服务器。此外,所有代码都是开源的或由我构建。
编辑 2: Web 框架:http://www.sparkjava.com/ .我通过框架而不是通过 Jetty (jetty-webapp-7.3) 提供静态媒体。这可能是改善内存使用的一些东西? HMI 网络应用程序的其他组件是 freemarker 模板引擎、gson、servlet-api-3、slf4j 和 log4j。
也许可以在启动 webapp 时尝试在线程中启动记录器和调度程序。然后只运行两个 JVM。一个用于 webapp,一个用于数据库服务器。
我使用的是 Java 7,它是一个 32 位系统。它有望用于生产用途(否则我有麻烦了)。
最佳答案
从一组单独的进程到单个进程通常不仅仅是“拨动开关”的问题。它们是根本不同的架构:
- 属于同一进程的线程共享某些它们可以“看到”的资源(内存空间、文件句柄等);他们可以以一种非常“轻量级”的方式相互通信和共享数据;
- 不同的进程在某种程度上是更“孤立”的单元:它们不能只是“偷看”彼此的内存、文件句柄等,而是必须以“更重”的方式相互通信(例如,通过套接字或操作系统提供的其他设施)。
现在,您从一种模型转移到另一种模型的难易程度以及它能给您带来多少 yield ,实际上取决于特定组件的功能以及它们之间的交互方式。我不熟悉你提到的一些组件,但从你的描述听起来好像你基本上有一堆相互连接的“黑盒子”,你将无法进行太多的重新架构。
因此,我建议查看各种组件的文档,看看它们是否允许您在启动时指定 VM 大小(或“堆大小”),然后尝试将组件降到最低他们需要。 (您的记录器进程大概不需要数百兆字节...)
Windows 原则上不应该“因为内存不足而关闭进程”。如果它需要将 JVM 堆的位交换进出虚拟内存 [*],它可能会开始像 hell 一样嘎嘎作响。但它实际上不应该关闭进程。另一方面,如果给定的 Java 应用程序在尝试从其堆中分配内存时遇到 OutOfMemoryError,它可能会决定关闭(或作为默认行为关闭,具体取决于其异常处理)。各种组件的日志表明发生了什么?
[*] 与 native 应用程序不同,Java 应用程序不能很好地处理虚拟内存,因为对于 Java 来说,它的内存是一个单独的“堆”,它实际上期望始终被分页。您应该避免分配总堆大小对于接近或大于机器中物理内存量的 JVM。
关于java - JVM 内存使用情况,一个带线程的 JVM 还是四个 JVM 用于我的四个应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11003167/