【问题标题】:Can multiple JVM processes share memory for common classes?多个JVM进程可以共享公共类的内存吗?
【发布时间】:2012-11-21 15:17:54
【问题描述】:

我想在我的 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 中实现这一点?我看到一些关于class data sharing 的页面,但这似乎只适用于核心运行时类。

【问题讨论】:

  • 这不适用于 HotSpot,它需要一个支持它的专用 JVM。在我的环境中,我遇到了同样的问题:我们有一个带有许多简单节点的分布式架构,每个节点都是在自己的 JVM 中的单独的 Jetty 服务器。它们每个可能需要 1-2 MB,但至少需要 64 MB。
  • 至于class data sharing一些人have tried it before

标签: java memory jvm shared-libraries


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 并非如此。当两个应用程序共享相同的代码(即完全相同的 Java 字节代码)时,它们已经知道彼此代码的所有信息。并且数据(即实例数据)无法共享,至少效率不高。
  • 我不是指数据,我指的是代码。如果共享代码不在安全位置,如何确保字节不会被恶意修改?或者,如何确保内存中的类不被恶意修改。
  • 这与攻击进程之间不共享的代码有何不同?如果虚拟机无法抵御此类攻击,则安全风险不会改变。
  • 因为您涉及某种共享内存。没错,问题不在文件系统级别(这已经存在),但是当您添加此共享内存时,您需要能够确保其中的内容不允许跨进程漏洞。
  • 我说的是 VM 已经存储 JIT 编译的 Java 代码的代码缓冲区,以及当 Java 从 jar 文件加载字节码时可以通过操纵字节码进行的攻击。如果 VM 可以抵御这些攻击,那么共享此代码缓冲区时不会有额外的风险。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-21
        • 1970-01-01
        • 2019-12-03
        • 2014-10-13
        • 2019-06-13
        相关资源
        最近更新 更多