JVM(Java Virtual Machine)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的导图
关于类加载器的介绍
JVM支持两大类加载器:引导类加载器,自定义类加载器(包括扩展类加载器和系统类加载器)
下面来仔细介绍三种加载器:
引导类加载器(BootStrap ClassLoader):
1.他使用C/C++实现的,嵌套在JVM内部
2.用来加载Java核心库,用来提供JVM自身需要的类
3.并不继承自java.lang.ClassLoader,没有父类加载器
4.加载扩展类的应用程序类加载器,并指定为他们的父类加载器
5.出于安全考虑,BootStrap启动类加载器只加载包名为java,javax,sun等开头的类
扩展类加载器(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()**可以获取到
下面是对于几种类加载器的演示:
在演示代码时发现一个问题:为什么ClassLoaderTest类的加载器跟系统类加载器一样,而String类则与引导类加载器一致呢?
1.首先我们看一下String是属于哪个包下的,翻看后发现属于java.lang包下,而自定义的ClassLoaderTest类呢
图中可见是自定义的com.study包下的,不是java,javax,sun包下的排除引导类加载器加载的可能,同时不是JDK安装目录下的加载类库,也排除扩展类加载器,所以就是系统类加载器与其一致。
由定义可知道系统类加载器的父类加载器是扩展类加载器,扩展类加载器的父类加载器是引导类加载器。那么上一个问题的推导顺序是按照什么规则呢?
它就是类加载器中比较重要的极致:双亲委派机制
工作原理:
1.如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求发送给他的父类的加载器去执行
2.如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终到达顶层的启动类加载器
3.父类可以完成类加载任务,就成功返回,若无法完成刺加载任务,子加载器才会尝试自己加载
看到了这个规则之后是不是对上面的问题有了更加深刻的理解了呢。