一、 JVM的位置
JVM是运行在操作系统之上的,与硬件没有直接的交互,但是可以调用底层的硬件,用JIN (Java本地接口调用底层硬件接口,了解下就好,已经过时了)
二、JVM体系结构概览
1. 类装载器ClassLoader (4个知识点,①概念,②种类(3种系统自带,1种自定义),③双亲委派机制,④沙箱安全机制)
1.1 类装载器的概念
负责加载class文件,class文件 ** 在文件开头有特定的文件标识 ** ,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
解释:Car.class 是由 .java 文件 经过编译而得来的 .class文件,存在本地磁盘
ClassLoader: 类转载器,作用就是加载并初始化 .class文件 ,得到真正的 Class 类,即模板 (此处不明白则带着疑问继续往下看,为什么叫模板)
Car Class : 由 Car.class 字节码文件,通过ClassLoader 加载并初始化而得,那么此时 这个 Car 就是当前类的模板,这个Car Class 模板就存在 【方法区】
car1,car2,car3 : 是由Car模板经过实例化而得,即 new出来的 --> Car car1 = new Car() , Car car2 = new Car() ,Car car3 = new Car() , 因此可知,由一个模板,可以得到多个实例对象,即模板一个,实例多个
所以,拿car1举例,car1.getClass 可以得到其模板Car 类,Car.getClassLoader() 可得到其装载器
1.2 类装载器的种类
1.2.1 虚拟机自带的加载器
① 启动类加载器 也叫根加载器 (Bootstrap) ,由C++编写 ,程序中自带的类, 存储在$JAVAHOME/jre/lib/rt.jar中,如object类等
② 扩展类加载器 (Extension) ,Java 编写 ,在我们平时看到的类路径中,凡是以javax 开头的,都是拓展包,存储在$JAVAHOME/jre/lib/ext/*.jar 中
③ 应用程序类加载器 (AppClassLoader),即平时程序中自定义的类 new出来的
Java也叫系统类加载器,加载当前应用的classpath的所有的类
1.2.2 用户自定义加载器
Java.lang.ClassLoader的子类,用户可以定制类的加载方式,即如果你的程序有特殊的需求,你也可以自定义你的类加载器的加载方式 ,进入ClassLoader的源码,其为抽象类,因此在你定制化开发的时候,需要你定义自己的加载器类来继承ClassLoader抽象类即可,即 MyClassLoader extends ClassLoader
所以,Java 的类的加载机制,永远是从 启动类加载器 --> 拓展类加载器 --> 应用程序类加载器 这样的一个顺序进行加载
1.3 类装载器的双亲委派机制
先举一个栗子,来说明下啥叫双亲委派,比如 有一个类叫 A.java ,当要使用A类时,类加载器要先去 启动类加载器(Bootstrap)中去找,如果找到就使用启动类加载器中的A类,不继续往下执行,但是如果找不到,则依次下放,去 拓展类加载器 中找,同理找到就用,找不到就继续下放,再去 应用程序类加载器中找,找到就用,此时找不到就会报classNotFund Exception的异常。
概念:
当一个类收到类加载请求,它首先不会尝试自己去加载这个类,而是先把这个请求委派给父类去完成,每一个层次类加载器都是如此,因此所有的类加载请求都是应该传到启动类加载器中的,只有当其父类加载器自己无法完成这个请求的时候(在他的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。
采用双亲委派的一个好处就是比如加载位于rt.jar包中的类java.lang.Object,不管是哪个加载器加载这个类,最终都是会委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同一个Object对象。
1.3 类装载器沙箱安全机制
通过双亲委派机制,类的加载永远都是从 启动类加载器开始,依次下放,保证你所写的代码,不会污染Java自带的源代码,所以出现了双亲委派机制,保证了沙箱安全
Execution Engine 执行引擎负责解释命令,提交操作系统执行。