【发布时间】:2011-08-22 06:39:24
【问题描述】:
是否所有运行的 Java 应用程序都使用同一个 JVM,或者“每个 Java 应用程序一个 JVM”是否适用? (比如应用程序是 IntelliJ IDEA、服务器和 NetBeans)
此外,分配的 JVM 和每个 Java 应用程序使用的进程之间是否有任何联系?
【问题讨论】:
-
这是一个很好的问题。 :)
是否所有运行的 Java 应用程序都使用同一个 JVM,或者“每个 Java 应用程序一个 JVM”是否适用? (比如应用程序是 IntelliJ IDEA、服务器和 NetBeans)
此外,分配的 JVM 和每个 Java 应用程序使用的进程之间是否有任何联系?
【问题讨论】:
一般来说,每个应用程序都会有自己的JVM实例和自己的OS级进程,每个JVM实例是相互独立的。
有一些实现细节,例如Class Data Sharing,其中多个 JVM 实例可能共享一些数据/内存,但这些对应用程序没有用户可见的影响(希望能够缩短启动时间)。
然而,一个常见的场景是运行多个 Web 应用程序的单个应用程序服务器(或“Web 服务器”),例如 Glassfish 或 Tomcat。在这种情况下,多个 Web 应用程序可以共享一个 JVM。
【讨论】:
每个 Java 应用程序有一个 JVM。除非你建立一个,否则它们之间不应该有任何联系,例如与网络。如果您在 IDE 中工作,您编写的代码通常在单独的 JVM 中运行。 IDE 通常会连接单独的 JVM 以进行调试。如果您正在处理多个 Web 应用程序,如果它们部署到同一个 Web 容器,它们可以共享同一个 JVM。
【讨论】:
理论上,您可以在 JVM 中运行多个应用程序。在实践中,它们可以通过各种方式相互干扰。 For example:
- JVM 有一组
System.in/out/err、一个默认编码、一个默认语言环境、一组系统属性等等。 如果一个应用程序更改了这些,则会影响所有应用程序。- 任何调用
System.exit()的应用程序都会杀死所有应用程序。- 如果一个应用程序线程失控,消耗过多的 CPU 或内存,也会影响其他应用程序。
【讨论】:
运行的 JVM 数量是调用的可执行文件的数量。 每个这样的应用程序都会调用自己的 java 可执行文件(java.exe/javaw.exe etx for windows),这意味着每个应用程序都在单独的 JVM 中运行。
【讨论】:
简短回答:通常,是的,每个 JVM 都会获得一个应用程序。 长答案:JVM 可以这样使用,这可能是最好的选择,但并非必须如此。
这完全取决于您认为什么是“应用程序”。 IDE 是一个很好的应用程序示例,它作为单个实体呈现给其最终用户(即我们),但实际上由多个底层应用程序(编译器、测试运行器、静态分析工具、打包器、包管理器、项目 /依赖管理工具等)。在这种情况下,IDE 会使用各种技巧来确保用户体验到集成体验,同时(在某种程度上)不受底层工具的各个变幻莫测的影响。其中一个技巧是在单独的 JVM 中执行一些事情,通过文本文件或通过应用程序级调试工具进行通信。
应用程序服务器(Wildfly、Glassfish、Websphere、Weblogic 等)是应用程序,其存在理由是充当其他应用程序在其中运行的容器。在这种情况下,从一个角度来看,每个应用程序只有一个 JVM(即一个 JVM 用于运行整个应用程序服务器)但实际上该 JVM 中包含多个应用程序本身,每个应用程序在它们自己的类加载器中逻辑上相互分离(减少意外的进程内串扰的可能性)。
所以,这完全取决于您认为application 是什么。如果您纯粹是在谈论“调用 'main()' 时运行的东西”,那么您正在查看每个 JVM 一个应用程序 - 当操作系统启动 JVM 时,JVM 运行单个类的 public static void main() 方法.
但是,一旦您的应用程序开始变得更加复杂,您的界限就会变得更加模糊。像 Intellij 或 Eclipse 这样的 IDE 将在同一个 JVM 或不同的 JVM 中重用许多与“javac”相同的东西,以及执行不同的工作(例如重新绘制屏幕)。并且(共享 JVM)应用程序服务器上的 Web 应用程序的用户实际上可能正在使用与可以通过命令行在本地使用的“核心”应用程序大致相同的“核心”应用程序。
【讨论】:
任何具有共享库的应用程序都将共享这些库的相同副本。 Java 有大量的共享库。但是,除了节省了一些内存之外,您不会注意到差异。
【讨论】:
这里有点晚了,但是此信息可能对某些人有用。在 Linux 系统中,如果你想知道有多少 JVM 正在运行,你可以试试这个命令
$ ps -ef | grep "[j]ava" | wc -l
ps用于列出进程,grep用于搜索包含“java”的进程,wc用于计算返回的行数
【讨论】:
实际上,这是一个可能有非常令人困惑的答案的问题。为了保持简短:
【讨论】: