jvm 之 类加载器

加载 >>  验证  >> 准备 >> 解析 >> 初始化 >> 使用 >> 卸载

· 加载 : 在硬盘上查找并通过io读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new 对象等等。

· 验证 : 校验字节码文件的正确性

· 准备 :给类的讲台变量分配内存,并赋予默认值

· 解析 :将符号引用替换为直接引用,该阶段会把一些静态方法  

· 初始化 :对类的静态变量初始化为指定的值,执行静态代码块

math类加载的时候,编译成class文件。

1:如果加载math,把math类从硬盘加载到内从中,

2:然后检查字节码的规则

3:然后把数据分配到内存中

4:栈内存的引用 指向堆内存的数据。

5:对静态变量初始化,执行静态代码块

类加载器的双亲委派机制:

启动类加载器:负责加载支撑JVM运行的位于JREd的lib目录下的核心类库,比如r.jar

扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包

应用程序类加载器:加载CLassPath路径下的类包,主要是加载自己写的那些类

自定义加载器:负责加载用户自定义路径 下的类包

观察loadClass源码可以明白,一个类加载器加载一个类时,首先会把加载动作委派给他的父加载器,如果父加载器无法完成这个加载动作时才由该类加载器进行加载。由于类加载器会向上传递加载请求,所以一个类加载时,首先尝试加载它的肯定是启动类加载器(逐级向上传递请求,直到启动类加载器,它没有父加载器),之后根据是否能加载的结果逐级让子类加载器尝试加载,直到加载成功。

比如我们自己写了一个com.test.T1类,假设我们没有自定义类加载器,那么这个类会由应用程序类加载器加载。应用程序类加载器加载时先把加载任务委派给扩展类加载器(父加载器),然后扩展类加载器再把加载任务委托给启动类加载器(父加载器),启动类加载器没有父加载器。于是它自己尝试加载,结果发现T1类并不在自己的记载类路径之中,于是告诉扩展类加载器(子加载器)自己无法加载该类。这时扩展类只好自己加载这个类,结果发现也无法加载该类,于是它也告诉应用程序类加载器这个消息,这时应用程序类加载器自己进行T1类的加载动作,加载成功。

双亲委派机制的存在意义
双亲委派是Java语言的一大创新。表明看起来,由于双亲委派机制的存在,类加载器的数量增多了不少,增加了程序的复杂性。不过存在既有道理。双亲委派机制让Java类体系变得稳定,有层次性能。特定的类由特定的类加载器加载,每次加载都委托父类的过程让类对象在内存中的数量保持为一个,让同类名的类无法被替换。

如果没有双亲委派机制,只有一个类加载器,我们自己写一个java.lang.Object类,也可以被加载,结果就是内存中有两个Object类,引用的时候会造成安全的问题。而且一些核心的类可能会被替换,导致重大的安全问题。

有了双亲委派机制,我们自己写的java.lang.Object类在加载时会被加载器委托给父加载器,在某一个父加载器中发现内存中已经存在了java.lang.Object类,那么将不会进行加载,这样就保证了特定的类只能有一个在内存中。
 

不采用双亲委派机制有意义: 同一个tomcat,有多个服务,他们的版本不一样,如果按照双亲委派机制,内存中同时只能存在一个类,这样的话,后来加载的服务,用的就是第一次服务记载的类。所以会有问题

发布了143 篇原创文章 · 获赞 41 · 访问量 59万+

猜你喜欢

转载自blog.csdn.net/qq_29257691/article/details/103699326
今日推荐