编写一个类,类全名如下:java.lang.String,要知道JDK也提供了一个java.lang.String。 那么程序会不会使用我们自己编写的String类?答案是不会,为什么呢?因为针对不同的来源,Java分了不同的ClassLoader来加载。
什么是类的加载机制?
Java代码经过编译后形成的.class文件,需要加载到虚拟机后才能运行。所以将.class文件加载到虚拟机的过程称之为类加载机制。
JVM使用Java类的流程如下:
- Java源文件---->编译---->class文件
- 类加载器ClassLoader会读取这个.class文件,并将其转化为java.lang.Class的实例。有了该实例,JVM就可以使用他来创建对象、调用方法等。
ClassLoader是以一种什么机制来加载Class的?
搞清楚这个问题,首先要知道,我们用到的Class文件都有哪些来源?
- Java内部自带的核心类,位于$JAVA_HOME/jre/lib,比如:rt.jar
- Java的扩展类,位于$JAVA_HOME/jre/lib/ext目录下
- 我们自己开发的类或项目开发用到的第三方jar包,位于我们项目的目录下,比如WEB-INF/lib目录
那么,针对这些Class,JDK是怎么分工的?谁来加载这些Class?
针对不同的来源,Java分了不同的ClassLoader来加载
- Java核心类,这些Java运行的基础类,由一个名为BootstrapClassLoader加载器负责加载。这个类加载器被称为“根加载器或引导加载器”
- 注意:BootstrapClassLoader不继承ClassLoader,是由JVM内部实现。所以通过java程序访问不到,得到的是null。
- Java扩展类,是由ExtClassLoader负责加载,被称为“扩展类加载器”。
- 项目中编写的类,是由AppClassLoader来负责加载,被称为“系统类加载器”。
那怎么知道这个类应该由BootStrapClassLoader来加载而不是其他加载器?这要看一下双亲委派机制。
什么是双亲委派机制?
所谓双亲委派机制,就是加载一个类,会先获取到一个系统类加载器AppClassLoader的实例,然后往上层层请求,先由BootstarpClassLoader去加载,如果BootStrapClassLoader发现没有,再下发给ExtClassLoader去加载,还是没有,才由AppClassLoader去加载。如果还是没有,则报错
解决提出的问题
JDK提供java.lang.String类,默认在rt.jar这个包里面,所以,默认会由BootstarpClassLoader加载,所以,我们自己编写的java.lang.String,都没有机会被加载到