JVM的体系结构图
先来看一下JVM的体系结构,如下图:

JVM的位置
JVM的位置,如下图:

JVM是运行在操作系统之上的,与硬件没有直接的交互,但是可以调用底层的硬件,用JIN(Java本地接口调用底层硬件)
JVM结构图中的class files文件
class files文件,是保存在我们电脑本地的字节码文件,.java文件经过编译之后,就会生成一个.class文件,这个文件就是class files所对应的字节码文件,如下图:

JVM结构图中的类加载器ClassLoader的解释
类加载器ClassLoader的作用
类加载器只有一个作用,就是负责把我们本地的.class字节码文件,加载到JVM中,以类模板的形式存在于JVM中。
类加载器加载的.class文件也是有要求的,并不是只要是后缀名为.class的文件,都可以被类加载器加载,这个.class文件的必须是.java文件经过编译后得到的字节码文件,也就是指这个.class文件的开头必须要是cafe babe字符单词,它的内容是经过加密后的二进制文件,但是此二进制使用十六进制表示出来的,如下图:

类加载器ClassLoader只负责加载.class文件,但至于他是否可以运行,由JVM中的执行引擎Excution Engine决定的。

解释:
Car.class是由.java文件编译得来的.class文件,存在本地磁盘。
ClassLoader:类加载器,负责加载并初始化 类文件,得到真正的Class类,即模板。
Car Class:由Car.class字节码文件,通过ClassLoader加载并且初始化得到,这个Car就是当前类的模板,这个Car Class模板就存在方法区。
car1,car2,car3:是由Car模板经过实例化而得,一个模板可以获得多个实例化对象。
拿car1举例,car1.getClass()可以得到模板Car类,Car.getClassLoader()可得到其装载器。
类加载器的种类
一共有四类。
虚拟机自带的加载器:
启动类加载器,也叫根加载器(BootStrap)。由C++编写,程序中自带的类,存储在 $JAVAHOME/jre/lib/rt.jar中,如object类等
扩展类加载器(Extension),Java编写,在我们看到的类路径中,凡是以Javax开头的,都是拓展包,存储在 $JAVAHOME/jre/lib/ext/*.jar 中,为什么会有扩展包?是因为原本的java包中在功能上,不能满足我们了,所以我们就在原本的java包的基础上扩展出了一些新的功能,而形成的新的包就叫做扩展包。
应用程序类加载器(AppClassLoader),即平时程序中自定义的类 new出来的
用户自定义的加载器:
Java.lang.ClassLoader的子类,用户可以定制类的加载方式,即如果你的程序有特殊的需求,你也可以自定义你的类加载器的加载方式 ,进入ClassLoader的源码,其为抽象类,因此在你定制化开发的时候,需要你定义自己的加载器类来继承ClassLoader抽象类即可,即 MyClassLoader extends ClassLoader
java类的加载机制
首先你需要知道,当java程序需要加载一个类的时候,会去找类加载器,然后找类加载器里面看是否有对应的类模板。
Java的类加载机制,永远是以 根加载器->拓展类加载器->应用程序类加载器 这样的一个顺序进行加载的。什么意思呢?就是如果能在BootStrapClassLoader类加载器的路径下找到对应的类模板,那么就不会再去扩展类加载器ExtensionClassLoader中找对应的类模板,如果能在扩展类加载器ExtensionClassLoader中找到对应的类模板,那么就不会去应用程序类加载器AppClassLoader中找对应的类模板。类加载器的父子级关系,如下图:

从上图可以看出根加载器BootStrapClassLoader是扩展类加载器ExtensionClassLoader的父级,扩展类加载器ExtensionClassLoader是应用程序加载器AppClassLoader的父级,如下图:

为什么说这样不会污染java自带的源代码呢?因为只要java的源代码中存在我们即将要加载的类,那么java程序在加载类的时候就会去顶层的根加载器BootstrapClassLoader路径下去寻找类模板,然后把这个类加载。你就比如假设我们自己写一个java.lang包,然后在这个包里面写一个String类,那么如果java源代码中没有java.lang.String这个类,java程序在用到这个类加载的时候,会用到应用程序类加载器AppClassLoader路径下的java.lang.String类,但是,我们都知道java源代码中是有java.lang.String这个类的,也即是在根加载器BootstrapClassLoader路径下有java.lang.String这个类,所以java程序在用到这个类加载它的时候,会加载根加载器BootstrapClassLoader路径下的java.lang.String类,而不会去加载应用程序类加载器AppClassLoader下的java.lang.String类,这样就保证了,我们在java程序的其它地方所用到的java.lang.String类的方法是正确的,怎么个正确法呢?因为啊,假设你是加载的应用程序加载器AppClassLoader路径里的java.lang.String类也即是你自己写的String类,那么在java程序的其它地方如果使用到了源代码java.lang.String类里面的方法该怎么办?这样是不是会出错?这其实也就是,你写的代码污染了人家写的源代码。
总结
到此这篇关于JVM中ClassLoader类加载器的文章就介绍到这了,更多相关JVM中ClassLoader类加载器内容请搜索社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持社区! |