3

我们正在尝试在共享环境中设置 Eclipse,即,它将安装在服务器上,并且每个用户都使用 VNC 连接到它。共享 Eclipse 有多种原因,其中之一是与 ClearCase 的适当集成。

我们发现 Eclipse 正在使用大量内存。我们想知道 Eclipse(JVM?)是否为每个用户/会话加载每个类一次,或者是否存在任何类型的已加载到内存中的对象共享?

这让我想到了一个一般的基本问题。当两个或更多用户同时访问主机时,有多少程序副本被加载到内存中。

是每个用户一个,还是在用户之间共享一个副本?

这里有两个问题:

1) 当两个或多个用户同时使用一个程序时,有多少个程序副本被加载到内存中?

2) 以上内容在 Java/JVM 世界中如何成立?

4

2 回答 2

2

Linux 允许在运行的进程之间共享二进制代码,即保存程序可执行部分的段被映射到virtual memory每个运行副本的空间中。然后每个进程获取自己的数据部分(堆栈、堆等)。

Java 或几乎任何其他解释型语言的问题在于,运行时 JVM 将字节码视为数据,并将其加载到堆中。Java 是半编译半解释的事实在此无关紧要。这会导致 JVM 可执行文件本身有资格由操作系统共享代码,但您的应用程序 Java 代码却不是。

于 2012-06-12T12:39:39.527 回答
1

通常,程序的单个副本(即文本段)被加载到 RAM 中并由所有实例共享,因此完全相同的只读内存映射物理页面(尽管可能/可能映射到不同地址空间中的不同地址,但它仍然是相同的记忆)。数据通常对每个进程都是私有的,即每个程序的数据都存在于单独的页面 RAM 中(尽管可以共享)。

问题是这里的实际程序只是 Java 运行时解释器,或 JIT 编译器。Eclipse 与所有 Java 程序一样,是数据而不是程序(但它被解释为程序)。该数据要么加载到私有地址空间并由 JVM 解释,要么由 JIT 编译器转换为可执行文件,从而生成(临时)可执行二进制文件,该二进制文件被启动。这意味着,原则上,每个 Java 程序都作为单独的副本运行,使用单独的 RAM。

现在,您当然可能很幸运,JVM 可能会将数据加载为共享映射,在这种情况下,字节码将在所有实例中占用相同的 RAM。但是,是否是这种情况只有 JVM 的作者才能知道,一般情况下,这不是您可以依赖的。

此外,根据 JIT 的聪明程度,它可能会将该二进制文件缓存一段时间,然后将其重用于相同的Java 程序,这将是非常有利的,不仅因为它节省了编译。从同一个可执行映像启动的所有实例共享相同的内存,所以这正是您想要的。
这甚至有可能在您的 JIT 编译器上完成 - 至少在某种程度上 - 因为编译是相当昂贵的,而且它是一种常见的优化。

于 2012-06-12T12:44:24.760 回答