JVM(Java Virtual Machine)Java虚拟机:一台抽象计算机

在百度百科是这么解释的:

centos java的虚拟机需要启动么 java虚拟机什么时候启动_加载


了解JVM,首先要了解的是JVM的生命周期。

JVM的生命周期分为三个阶段:虚拟机的启动,虚拟机的执行及虚拟机的退出。

虚拟机的启动:Java虚拟机是铜锅引导类加载器(bootstrap classloader)创建一个初始类(inital class)来完成,这个类由虚拟机的具体实现指定

虚拟机的执行:

1.一个运行之中的Java虚拟机有一个清晰的任务:执行Java程序

2.程序开始执行时他才执行,程序结束时就停止

3.执行一个所谓的Java程序的时候,真正在执行的是一个叫做虚拟机的进程

虚拟机的退出:

1.程序正常的执行结束

2.遇到异常或错误而异常终止

3.操作系统出现错误而导致Java虚拟机进程终止

4.某线程调用Rantime类或System类的exit方法,或Runtime类的halt方法,并且Java安全管理器也循序这次exit或halt操作。

关于JVM的导图

centos java的虚拟机需要启动么 java虚拟机什么时候启动_Java_02

关于类加载器的介绍

JVM支持两大类加载器:引导类加载器,自定义类加载器(包括扩展类加载器和系统类加载器)

下面来仔细介绍三种加载器:

引导类加载器(BootStrap ClassLoader):

1.他使用C/C++实现的,嵌套在JVM内部

2.用来加载Java核心库,用来提供JVM自身需要的类

3.并不继承自java.lang.ClassLoader,没有父类加载器

4.加载扩展类的应用程序类加载器,并指定为他们的父类加载器

5.出于安全考虑,BootStrap启动类加载器只加载包名为javajavaxsun等开头的类

扩展类加载器(Extension ClassLoader):

1.使用Java编写,由sun.misc.Launcher$ExtClassLoader实现。

2.派生于ClassLoader类

3.父类加载器为启动类加载器

4.从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录jre/lib/ext子目录(扩展目录)下加载类库,如果用户创建的Jar放在此目录下,也会自动由扩展类加载器加载

系统类加载器(AppClassLoader,虚拟机自带的加载器)

1.使用java编写,由sun.misc.Laucher(dollar符,类似格式见扩展类加载器第一条)AppClassLoader实现(两个dollar符会变换字体,有不太好的体验,请谅解)

2.派生于ClassLoader类

3.父类加载器为扩展类加载器

4.负责加载环境变量classpath或系统属性java.class.path指定路径下的类库

5.该类加载是程序默认的类加载器,一般来说Java应用类由他完成

6.**ClassLoader.getSystemClassLoader()**可以获取到

下面是对于几种类加载器的演示:

centos java的虚拟机需要启动么 java虚拟机什么时候启动_加载_03


在演示代码时发现一个问题:为什么ClassLoaderTest类的加载器跟系统类加载器一样,而String类则与引导类加载器一致呢?

1.首先我们看一下String是属于哪个包下的,翻看后发现属于java.lang包下,而自定义的ClassLoaderTest类呢

centos java的虚拟机需要启动么 java虚拟机什么时候启动_java_04


图中可见是自定义的com.study包下的,不是java,javax,sun包下的排除引导类加载器加载的可能,同时不是JDK安装目录下的加载类库,也排除扩展类加载器,所以就是系统类加载器与其一致。

由定义可知道系统类加载器的父类加载器是扩展类加载器,扩展类加载器的父类加载器是引导类加载器。那么上一个问题的推导顺序是按照什么规则呢?

它就是类加载器中比较重要的极致:双亲委派机制

工作原理:

1.如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求发送给他的父类的加载器去执行

2.如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终到达顶层的启动类加载器

3.父类可以完成类加载任务,就成功返回,若无法完成刺加载任务,子加载器才会尝试自己加载

看到了这个规则之后是不是对上面的问题有了更加深刻的理解了呢。