一台机器上能起多少个JVM?
- 一台机器(操作系统)能启动多个JVM进程,各个JVM进程有独自的数据空间和代码空间,互不影响,并且每调用java命令之后(执行启动类的main函数),就是启动一个JVM实例
- 只要你内存够大,配置足够高,可以启动多个JVM,甚至是不同厂商、不同版本的JVM
一个JVM运行时只能容忍一个“包含main方法的JAVA类”?
- 一个JVM的运行, 必须指定某个Java类的main方法去运行. 也就是一个JVM的运行, 只依赖于一个含main方法的java类. 实际上等同于 执行了java Java类名 这个命令.
- 就算你使用下面的方法, 运行One.main(), 在One.main()中显示去调用Two.main()也无法达到启动另一个JVM的效果, 因为还是在One.main()的JVM中运行, 这个时候的Two.main()就和一般情况下的方法调用没有任何差别.
public class One {
public static void main(String[] args) {
System.out.println("One.main");
Two.main(args);
}
}
public class Two {
public static void main(String[] args) {
System.out.println("Two.main");
}
}
- 也可通过另一个线程启动其他main线程
package jvmtest;
public class One {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
Two.main(args);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
while (true) {
System.out.println("one thread!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Two {
public static void main(String[] args) {
System.out.println("two thread");
}
}
执行情况为:
上图可以看出只能有一个主线程在执行,其他的并不是主线程,是普通线程,或者普通方法调用。
什么是JVM
- java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。因此在运行时,Java源程序需要通过编译器编译成为.class文件。众所周知java.exe是java class文件的执行程序,但实际上java.exe程序只是一个执行的外壳,它会装载jvm.dll(windows下,下皆以windows平台为例,linux下和solaris下其实类似,为:libjvm.so),这个动态连接库才是java虚拟机的实际操作处理所在。
参考文章: 什么是JVM - JRE(java运行时环境)由JVM构造的java程序的运行环,也是Java程序运行的环境,但是他同时一个操作系统的一个应用程序一个进程,因此他也有他自己的运行的生命周期,也有自己的代码和数据空间。JVM在整个jdk中处于最底层,负责于操作系统的交互,用来屏蔽操作系统环境,提供一个完整的Java运行环境,因此也就虚拟计算机。操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境:1) 创建JVM装载环境和配置 2) 装载JVM.dll 3) 初始化JVM.dll并挂界到JNIENV(JNI调用接口)实例4) 调用JNIEnv实例装载并处理class类。
参考文章: JVM介绍
进程层面理解JVM
虚拟机是运行在操作系统之中的,那么什么东西才能在操作系统中运行呢?当然是进程,因为进程是操作系统中的执行单位。可以这样理解,当它在运行的时候,它就是一个操作系统中的进程实例,当它没有在运行时(作为可执行文件存放于文件系统中),可以把它叫做程序。
java命令首先启动虚拟机进程,虚拟机进程成功启动后,读取参数“HelloWorld”,把他作为初始类加载到内存,对这个类进行初始化和动态链接(关于类的初始化和动态链接会在后面的博客中介绍),然后从这个类的main方法开始执行。也就是说我们的.class文件不是直接被系统加载后直接在cpu上执行的,而是被一个叫做虚拟机的进程托管的。首先必须虚拟机进程启动就绪,然后由虚拟机中的类加载器加载必要的class文件,包括jdk中的基础类(如String和Object等),然后由虚拟机进程解释class字节码指令,把这些字节码指令翻译成本机cpu能够识别的指令,才能在cpu上运行。
从这个层面上来看,在执行一个所谓的java程序的时候,真真正正在执行的是一个叫做Java虚拟机的进程,而不是我们写的一个个的class文件。这个叫做虚拟机的进程处理一些底层的操作,比如内存的分配和释放等等。我们编写的class文件只是虚拟机进程执行时需要的“原料”。这些“原料”在运行时被加载到虚拟机中,被虚拟机解释执行,以控制虚拟机实现我们java代码中所定义的一些相对高层的操作,比如创建一个文件等,可以将class文件中的信息看做对虚拟机的控制信息,也就是一种虚拟指令。
- 当Java应用启动时先启动JVM,创建好JAVA必备的运行环境,然后加载和创建Java的main主线程开始执行我们的程序,本质上只有一个JVM进程,里边有一个主线程和其他线程。应用程序在操作系统级别不可见,操作系统只能看见JVM进程,应用程序必须在JVM中才能执行。
- 而C++或者C语言,只需要把应用编译好,然后执行就创建了一个该应用的进程,也就是该应用的单进程单线程模型。
重要参考文献:深入理解JVM到底是什么
一个JVM中能否启动多个main(服务)
- 当然可以,在主线程的main函数中创建不同的线程通过反射分别加载本地的main类,然后启动这些main类,本质上是线程这些main是普通的线程而已。
- 在JVM中执行的只能是线程,因为JVM是一个进程。
- 在JVM中可以采用多线程的方式同事启动多个服务。