A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 长沙-小知姐姐 于 2019-3-29 19:08 编辑

       首先知道我们写的.Java源码文件,经过javac.exe编译后成为了.class文件,.class文件中描述了类的各种信息,最终都需要加载到虚拟机之后才能运行和使用。而虚拟机如何加载这些.class文件?.class文件的信息进入到虚拟机后会发生什么变化?下面我们就来了解一下java类加载的过程:
       我们写的类,首先会编译成字节码文件,然后通过Java 中的类加载器负责将我们需要使用的类,加载进内存。而类加载器大致可以分成两类,一类是系统提供的,另外一类则是由 Java 应用开发人员编写的。
       当然jvm启动的时候,并不是一次性加载所有的类,而是根据需要动态去加载类,主要分为隐式加载和显示加载。
       隐式加载:程序代码中不通过调用ClassLoader来加载需要的类,而是通过JVM类自动加载需要的类到内存中。例如,当我们在类中继承或者引用某个类的时候,JVM在解析当前这个类的时,发现引用的类不在内存中,那么就会自动将这些类加载到内存中。
  显示加载:代码中通过Class.forName(),this.getClass.getClassLoader.LoadClass(),自定义类加载器中的findClass()方法等。

1.    引导类加载器(bootstrap class loader):

       它用来加载 Java 的核心库(jre/lib/rt.jar),是用原生C/C++代码来实现的,并不继承自java.lang.ClassLoader。加载扩展类和应用程序类加载器,并指定他们的父类加载器,因为不是java编写,所以在java中并无法展现,也获取不到。 但是我们可以通过简单代码来查看它所负责加载类的路径:
package test;
public class Test01{
public static voidmain(String[]args){
System.out.println(System.getProperty("sun.boot.class.path"));
}
}

打印结果如下:

D:\ develop\Java\jdk1.8.0_20\jre\lib\resources.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\lib\rt.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\lib\sunrsasign.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\lib\jsse.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\lib\jce.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\lib\charsets.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\lib\jfr.jar;D:\Program
Files\Java\jdk1.8.0_20\jre\classes

2.    扩展类加载器(extensions class loader):

它用来加载 Java 的扩展库(jre/ext/*.jar)。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。 也可以通过System.out.println(System.getProperty("java.ext.dirs"))查看加载类文件的路径。

打印结果如下:
D:\develop\Java\jdk1.8.0_20\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext

3.    系统类加载器(system class loader):
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它,sun.misc.Launcher$AppClassLoader@58644d46


4.    自定义类加载器(custom class loader):
除了系统提供的类加载器以外,我们开发人员自己可以通过继承 java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。


5.     类加载器的继承关系


ExtClassLoader,AppClassLoder继承URLClassLoader,而URLClassLoader继承ClassLoader,BoopStrapClassLoder不在上图中,因为它是由C/C++编写的,它本身是虚拟机的一部分,并不是一个java类。

jvm加载的顺序:BoopStrap ClassLoder-ExtClassLoader->AppClassLoder

6.   类加载机制-双亲委托机制
       咱先得弄清楚双亲委托机制到底是什么东西,它是是通过类加载器将class文件加载到虚拟机中以备调用,但是我们可以自己也写一个java.lang.String,来冒充jdk中的String, 假设这两个String都还没有加载,那么首先自身的加载器 AppClassLoader会去内存中找,找不到,直到bootstrap也在内存中找不到,那这时bootstrap会加载rt.jar中的String,至此加载结束,你自己的高仿是加载不到的。

       假设内存中原有的String已经加载,那么更简单,你兴致冲冲的写完了高仿准备装逼的时候,bootstrap 或者AppClassLoader 已经在内存中找到了(至于哪个加载器寻找哪一个区域的内存空间我不是很清楚 所以也不敢妄下定论)那你的高仿又失去了表现机会,这样的加载模式,保证了java自身类的安全。

// ClassLoader源码解析
游客,如果您要查看本帖隐藏内容请回复


首先:需要在E盘下创建一个lib文件夹,再把idea项目中srccom文件夹直接复制 Elib文件夹即可。
打印结果如下:


备注:以上代码均在JDK1.8版本下进行,JDK1.9类加载器略有不同。







0 个回复

您需要登录后才可以回帖 登录 | 加入黑马