每个Java应用程序是否有一个JVM?

105

所有运行的Java应用程序是否使用相同的JVM,还是“每个Java应用程序一个JVM”适用?(例如,假设应用程序是IntelliJ IDEA、服务器和NetBeans)

此外,分配的JVM和每个Java应用程序使用的进程之间是否有任何连接?


3
这是一个非常好的问题。 :) - jamie
8个回答

91
通常情况下,每个应用程序都会获得自己的JVM实例和自己的操作系统级进程,每个JVM实例都是相互独立的。
有一些实现细节,比如类数据共享,多个JVM实例可能会共享一些数据/内存,但这对应用程序没有用户可见的影响(除了希望改进启动时间)。
然而,一个常见的场景过去是单个应用服务器(或“Web服务器”)如Glassfish或Tomcat运行多个Web应用程序。在这种情况下,多个Web应用程序可以共享一个JVM。然而,随着容器化和微服务的发展,这种设置变得相对较少见。

29

每个Java应用程序都有一个JVM。除非您建立连接(例如通过网络),否则它们之间不应该有任何联系。如果您在IDE中工作,则编写的代码通常在单独的JVM中运行。IDE通常会连接单独的JVM进行调试。如果您正在处理多个Web应用程序,则它们可以共享同一个JVM,如果它们被部署到同一个Web容器中。


16

理论上,您可以在JVM中运行多个应用程序。但实际上,它们可能以各种方式相互干扰。 例如

  • JVM有一组System.in/out/err,一个默认编码,一个默认语言环境,一组系统属性等等。如果一个应用程序更改了这些内容,它会影响所有应用程序。
  • 任何调用System.exit()的应用程序都会关闭所有应用程序。
  • 如果一个应用程序线程失控,并消耗太多CPU或内存,则也会影响其他应用程序。

11

简短回答:通常情况下,是的,您将获得一个JVM应用程序。

长回答:JVM可以那样使用,并且这可能是最佳选择,但并不一定需要。

这完全取决于您认为“应用程序”是什么。IDE是一个很好的例子,它被呈现给最终用户(即我们)作为一个单一实体,但实际上由多个基础应用程序组成(编译器、测试运行程序、静态分析工具、打包程序、包管理器、项目/依赖项管理工具等)。在这种情况下,IDE使用各种技巧来确保用户体验到集成体验,同时还免受基础工具的个别变化的干扰。其中一个技巧是在单独的JVM中执行某些操作,通过文本文件或应用级调试工具进行通信。

应用程序服务器(Wildfly、Glassfish、Websphere、Weblogic等)是作为其他应用程序运行的容器的应用程序。在这种情况下,从某种角度来看,每个应用程序都有一个单独的JVM(即使用一个JVM来运行整个应用程序服务器),但实际上,每个应用程序在该JVM内部是独立的,每个应用程序在自己的类加载器中逻辑上与其他应用程序分离(减少了意外进程交叉对话的可能性)。

因此,这完全取决于您认为“应用程序”是什么。如果您纯粹谈论“在调用'main()'时运行的东西”,那么您将看到一个JVM每个应用程序 - 当操作系统启动JVM时,JVM运行单个类的public static void main()方法。

但是,一旦您的应用程序变得更加复杂,边界就变得更加模糊。例如Intellij或Eclipse这样的IDE将在同一个JVM或不同的JVM中重复使用许多与'javac'相同的内容,以及进行不同的工作(例如重新绘制屏幕)。而共享JVM的应用程序服务器上的Web应用程序的用户实际上可能正在使用与通过命令行本地使用的“核心”应用程序相同的内容。


9

运行的JVM数量是调用的可执行文件数量。每个应用程序都会调用自己的java可执行文件(例如Windows系统中的java.exe / javaw.exe),这意味着每个应用程序都在单独的JVM中运行。


5
任何具有共享库的应用程序都将共享这些库的同一副本。Java具有相当数量的共享库。但是,除了节省一些内存外,您不会注意到任何区别。

2

虽然有点晚了,但这些信息可能对某些人有用。在Linux系统中,如果你想知道有多少个JVM正在运行,可以尝试使用以下命令:

$ ps -ef | grep "[j]ava" | wc -l

ps 命令用于列出进程,grep 命令用于搜索包含 "java" 的进程,wc 命令用于计算返回的行数。


0

实际上,这是一个可能会有非常混乱答案的问题。简单来说:

  1. 每个Java进程、每个JVM都是如此。
  2. Runtime和ProcessBuilder遵循此规则。
  3. 使用反射加载jar文件,然后执行主函数不会生成新的JVM。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接