深入分析Java Web技术内幕第六章

深入分析Java Web技术内幕读书笔记

chapter6. 深入分析ClassLoader工作机制

ClassLoader就是类加载器,负责将Class加载到JVM中。除了这个功能外,还有一个作用就是审查每个类应该由谁加载,此外,还可以将Class字节码重新解析成JVM统一要求的对象格式。

6.1 ClassLoader类结构分析

ClassLoader的主要结构信息:
defineClass:将byte字节流解析成JVM能够识别的Class对象
findClass:实现类的加载规则
loadClass:获取这个类的Class对象

6.2 ClassLoader的等级加载机制

1、Bootstrap ClassLoader:接待室服务自身的,主要加载JVM自身工作需要的类,只是一个类的加载工具。用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下内容),是用原生代码来实现的,并不继承自java.lang.ClassLoader。加载扩展类和应用程序加载器,并指定他们的父类加载器。

2、ExtClassLoader:JVM自身的一部分,这个类加载器理解为是那些与这个大会合作单位的员工会员,这些会员既不是JVM内部,也和普通的外部会员不同,所以由这个类加载。

用来加载Java的扩展库(JAVA_HOME/jre/ext/*.jar,或者java.ext.dirs路径下的内容。)Java虚拟机的实现会提供一个扩展库目录,该类加载器在此目录里面查找并加载Java类。由sun.misc,Launcher$EXTClassLoader实现

3、AppClassLoader:专门接待会员服务的,父类是ExtClassLoader,服务目标是广大普通会员,所有在System.getProperty(“java.class.path”)目录下的类都可以被这个类加载,这个目录就是我们经常用到的classpath。一般来说,Java应用的类都是由它来完成加载的,由sun.misc.Launcher$AppClassLoader实现
在这里插入图片描述
JVM的机制是自底向上检查类是否被加载,自顶向下尝试加载类
在这里插入图片描述
JVM加载class文件到内存的两种方式

1、隐式加载:不通过在代码里调用ClassLoader来加载需要的类,而是通过JVM自动加载需要的类到内存的方式

2、显示加载:通过ClassLoader加载

6.3 如何加载class文件

如图所示为ClassLoader加载一个class文件到JVM时需要经过的步骤
在这里插入图片描述

  1. 找到.class文件并把这个文件包含的字节码加载到内存中
  2. a)字节码验证 b)Class类数据结构分析及相应的内存分配 c)符号表链接
  3. 类中静态属性和初始化赋值以及静态块的执行

(1)加载字节码到内存
设置ClassLoader的搜索路径,创建URLClassPath对象时会根据传过来的URL数组中的路径来判断是文件还是jar包,根据路径不同分别创建FileLoader或JarLoader,或使用默认的加载器,当JVM调用findClass时由这几个加载器来将class文件的字节码加载到内存中

(2)验证与解析
字节码验证:类装入器对于类的字节码检测,确保格式、行为正确
类准备:在这个阶段准备代表每个类中定义的字段、方法和实现接口所必须的数据结构
解析:在这个阶段类装入器装入类所引用的其他所有类

(3)初始化Class对象
类中包含的静态初始化器都被执行,末尾静态字段被初始化为默认值

6.4 常见加载类错误分析

6.4.1 ClassNotFoundException

显示加载类三种方法:

  • Class.forName();

  • ClassLoader.loadClass()

  • ClassLoader.findSystemClass()

这类错误因为JVM要加载指定文件的字节码到内存是,并没有找到这个文件对应的字节码,也就是这个文件并不存在。
解决办法就是检查在当前的classpath目录下有没有指定的文件存在。

如果不知道当前的classpath路径,就可以通过命令来获取

this.getClass().getClassLoader().getResource("").toString()

6.4.2 NotClassDefFoundError

类可能没加包名。

解决办法:确保每个类引用的类都在当前的classpath下

6.4.3 UnsatisfiedLinkError

可能是误删了lib文件

6.4.4 ClassCastException

JVM在做类型转换时按照如下规则检查

对于普通对象,对象必须是目标类的实例或者目标类的子类的实例

对于数组类型,目标类型必须是数组类型或java.lang.Object、java.lang.Cloneable、java.io.Serializable

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值