6

我想在我的 Web 服务器上运行多个 Java 进程,每个 Web 应用程序一个。我正在使用一个具有大量支持类和 jar 文件的 Web 框架(Play),并且 Java 进程使用大量内存。一个 Play 进程显示大约 225MB 的“驻留私有”内存。(我正在使用 Java 1.7.0_05 的 Mac OS X 上对此进行测试。)特定于应用程序的代码可能只有几 MB。我知道典型的 Java Web 应用程序是添加到一个服务器进程(Tomcat 等)的 jar,但似乎运行 Play 的标准方式是作为独立的应用程序/进程。如果这些是 C 程序,那 200MB 中的大部分将是共享库,并且不会在每个应用程序中复制。有没有办法在 Java 中实现这一点?我看到一些关于类数据共享的页面,但这似乎只适用于核心运行时类。

4

4 回答 4

5

目前,对于 Oracle VM,这是不可能的。

但我同意,这将是一个不错的功能,特别是因为 Java 拥有自动执行此操作所需的所有信息。

最重要的是,我认为 JIT 是它无法工作的唯一原因:JIT 将运行时行为考虑在内。因此,如果应用 A 使用与应用 B 不同的模式的某些代码,则会导致在运行时生成不同的汇编代码。

但是,通常的“模式”是“这段代码的使用频率”。因此,如果应用程序 A 经常调用某个方法而 B 没有,他们仍然可以共享代码,因为 A 已经为优化/编译它付出了代价。

您可以尝试将多个应用程序作为 WAR 文件部署到单个 VM 中。但根据我的经验,这通常会导致无法正确清理线程本地变量或关闭挂钩的代码出现问题。

于 2012-11-21T15:33:28.600 回答
4

IBM JDK 有一个 jvm 参数来实现这一点。查看@http ://www.ibm.com/developerworks/library/j-sharedclasses/

这将其带到下一步:http ://www.ibm.com/developerworks/library/j-multitenant-java/index.html

于 2013-12-04T00:04:42.437 回答
1

在 JVM 实例之间共享内存的问题在移动平台上更为紧迫,据我所知,Android 在 Zygote 中有一个非常聪明的解决方案:初始化 VM,然后在运行应用程序时对其进行fork()编辑。Linux 在 RAM 页面上使用写时复制,因此大部分数据不会被复制。

如果您在 Linux 上运行并想尝试使用 Dalvik 作为您的 VM(我看到声称在 Dalvik 上有一个工作的 tomcat 端口),那么移植这个解决方案是可能的。我预计这将是一项巨大的工作,最终为您节省几美元的内存升级。

于 2012-11-21T15:40:42.377 回答
1

如果您使用支持虚拟主机的 servlet 容器(我相信 Tomcat 会这样做),您将能够使用play2-war-plugin。从 Play 2.1 开始,始终作为根应用程序的要求将被取消,因此您可能能够使用任何 servlet 容器。

需要记住的一件事是,如果您可能需要调整 war 文件以将内容从WEB-INF/libservlet 容器的 lib 目录中移动,以避免再次加载所有类,并且如果它使用单例或其他形式的类共享,这可能会影响您的应用程序数据。

于 2012-11-21T15:31:42.720 回答