首页 > 学院 > 开发设计 > 正文

JVM理解

2019-11-06 07:46:23
字体:
来源:转载
供稿:网友

一台机器上能起多少个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虚拟机的实际操作处理所在。 参考文章: 什么是JVMJRE(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中可以采用多线程的方式同事启动多个服务。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表