ClassLoader的工作机制

本文中主要介绍类加载器的工作机制

一:首先什么是类加载器?

  类加载器就是用来加载java类到java虚拟机中。java源程序经过编译之后形成字节码文件,类加载器将字节码文件加载到内存中,并转换成java.lang.Class的一个实例对象。

  JVM是基于栈操作的:所有的操作都要经过进栈和出栈操作。基于栈操作的优点:将运行时的优化工作和执行编译时优化的执行引擎相结合,从而起到优化Java字节码的目的。

二: 类加载器的作用:

  1. 将编译后的class字节码文件加载到JVM中。会在加载的过程进行审查每个类有哪个类加载器加载?加载哪个类?  实际上是存在一种父级优先的等级结构
  2. 将字节码文件重新解析成JVM统一要求的对象格式。

三:类加载器的分类

  •   BootStrap ClassLoader:加载的过程是由JVM自身决定的,具体如何加载,加载哪个类都是有JVM自身控制的,实际上他并不符合JVM规范,不存在等级结构,没有父加载  器,也没有子加载器。他仅仅是作为一个加载工具存在
  •      ExtClassLoader:虽然他本身是JVM的一部分,但是加载并不是有JVM自身加载,他服务的特定目标是在System.getProperties("java.ext.dirs")目录下
  •      APPClassLoader :是ExtClassLoader类加载器的子类,主要加载位于classpath目录下的类 System.getProperties("java.class.path")

四:JVM加载字节码文件的两种方式

  1. 隐式加载:不调用类加载器,将需要的类自动加载到内存中 例如:当前类需要外部类的引用时,就会触发隐式加载
  2. 显式加载:调用 this.getClass(),this.getClassLoader(),Class.forName(class)等方式完成的加载就是显式加载

两种加载方式可以混合使用,显式加载自定义的类,如果该类中有其他类的引用,就会触发隐式加载。

 五:类加载常见的错误分析

  • ClassNotFoundException:显式加载字节码文件时,找不到对应的字节码文件异常,发生这种问题的原因是在对应的classpath下可能没有对应的字节码文件,导致异常的发生;解决方案:到对应的classpath下面检查是否有对应的字节码文件,通过this.getClass().getClassLoader().getResources().toString();获得path的路径
  • NotClassDefFoundError:类不存在异常 产生的原因是:new关键字,引用类,继承接口或者类,方法参数用有引用,这些都会导致此种异常的发生。在隐式加载这些类时可能出现类不存在的异常。
  • ClassCastException:强制类型转换时出现这个错误   

  在JVM进行类型转换时会进行自动检查  

  1.   普通对象:必须是目标类的实例对象或者子类对象;如果是接口,对象是该接口的子类对象
  2.       数组对象:目标类必须是数组类型或者java.lang包下的Object ,Clonable,java.io包下的Serializable

  解决类型转换异常的方法:显式指明对象类型;通过instanceof判断是否是目标对象类型,然后在进行类型转换。

六:JVM的体系结构以及工作方式

  • JVM是通过模拟真实计算机,从而达到一个真实计算机所具有的计算功能的体系结构。以计算机为中心的真实计算机的体系结构
    •   指令集:计算机能够识别的机器语言的所有命令集合
    •        计算单元:能够识别并且控制指令执行的功能模块
    •        寄存器:中央处理器的核心组件,用来暂存,指令,地址和数据
    •        存储单元:能够存储计算机操作数和操作结构的单元,例如:内存和磁盘
    •        寻址方式:地址的范围,最小地址和最大地址范围以及地址的运行规则
  •   JVM的体系结构:
    •    执行引擎:相当于CPU,控制指令执行。解析字节码文件,得到解析结果。
    •         pc寄存器:每个线程启动的时候都会创建一个pc寄存器。寄存器中保存的是当前执行的JVM指令的地址。保存下一条将要执行的指令地址的寄存器是:pc寄存器。他总是保存着下一条将要执行的指令地址。地址可以是一个本地指针,也可以是方法中相对于方法起始指令的地址。
    •         本地方法栈:保存native方法的区域
    •         堆:保存的是创建的对象实例。所有的类对象都是通过new创建,创建对象后会在栈中创建该对象的引用。
    •         方法区:又叫做静态区:保存的是方法数据,类,静态变量,静态方法,常量和成员方法
    •         运行时常量池:存放的是类和接口的常量,除此之外,还有成员方法和成员变量的引用。JVM运行时就是通过这些引用来找到实际的地址

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏七夜安全博客

无线安全专题_破解篇03--打造个人字典

12840
来自专栏北京马哥教育

手把手教你用500行 Python 代码实现模板引擎

引言 大多数程序包含大量的逻辑,以及少量文本数据。编程语言被设计成适合这种类型的编程。但是一些编程任务只涉及一点逻辑,以及大量的文本数据。 对于这些任务,我...

50950
来自专栏c#开发者

[原创]PipelineTools 文件传输工具

功能模块只有 1/文件目录-〉文件目录 2/文件目录-〉MSMQ 3/MSMQ-〉MSMQ 4/MSMQ -〉文件目录 在传输MSMQ是文件不能超过4M 下载文...

38170
来自专栏ccylovehs

JDK动态代理与CGLib动态代理

JDK1.3以后java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,动态代理是实现AOP的绝好底层技术。

43010
来自专栏运维技术迷

Redis全局命令

redis有5种数据结构,他们是键值对中的值,对于键来说有一些通用的命令。 查看所有键 语法:keys * [root@vultr ~]# redis-cli ...

35170
来自专栏Web项目聚集地

你真的懂「类的加载机制」吗?

高广超 :多年一线互联网研发与架构设计经验,擅长设计与落地高可用、高性能互联网架构。目前就职于美团网,负责核心业务研发工作。本文首发在 高广超的简书博客,欢迎点...

18430
来自专栏http://www.cnblogs.com

day5-json和pickle序列化

一.json模块 序列化:把一个对象的形态改变一下,使他能够存放在文件中,或者在网络上传输,序列化也叫持久化,是把对象存储到永久介质中,这样就不会因为掉电而丢失...

374140
来自专栏娱乐心理测试

vue 方法回调通知执行下一个方法

在项目中有很多这样的需求,在一个方法执行完成拿到数据后才可以执行下一个方法,这就需要在第一个方法执行完后有个回调函数通知下一个方法可以执行了。

26320
来自专栏Python小屋

Python快速计算Fibonacci数列中第n项的方法

from time import time from functools import lru_cache def fibo1(n): '''递归法''' ...

33670
来自专栏猿人谷

unix共享内存要点

共享内存优点:     1.在进程之间不通过内核传递数据,即不通过系统调用拷贝数据,达到快速,高效的数据传输。     2.随内核持续     *nix的共享内...

19350

扫码关注云+社区

领取腾讯云代金券