写点什么

JVM 进阶 (十四)——初识 JAVA 类加载机制

  • 2022 年 5 月 19 日
  • 本文字数:1589 字

    阅读完需:约 5 分钟

JVM进阶(十四)——初识JAVA 类加载机制

从本篇博文开始,我们就进入虚拟机类加载机制的学习了。那么什么是类加载呢?当我们写完一个 Java 类的时候,并不是直接就可以运行的,它还要编译成.class(字节码)文件,再由虚拟机解释给当前的操作系统去执行。这些过程都是我们看不见的,我们能看见的也就是一个.class文件。既然虚拟机要解释这些.class文件给当前的操作系统听,那么他怎么获得这些.class文件呢?虚拟机获得这些.class文件的过程就是类加载了。


所以,总结来说就是:虚拟机将.class文件从磁盘或者其他地方加载到内存,并同时对文件中的数据进行校验转换解析初始化,最终形成可以被虚拟机直接识别的类型,这就是类加载机制


首先我们来看看类的一个生命周期:



总共有加载、验证、准备、解析、初始化、使用卸载七个阶段。其中前面的 5 个阶段就是我们要说的类加载机制了,验证、准备、解析阶段又统称为连接阶段。注意:解析阶段不一定会在准备阶段之后就执行,也有可能会在初始化阶段之后,这是为了支持 JAVA 的动态绑定的特性。


什么是动态绑定呢?相信大家都知道 JAVA 的 4 大特性吧:封装、继承、抽象、多态。其实多态就可以理解为动态绑定。多态的实现机制就是:**父类或者接口可以创建他们的子类或者实现类的实例对象。**简单的来说就是:父类可以 new 出子类,接口可以 new 出他的实现类。


多态通俗来说就是:父类 A 有一个方法 function(),子类 B,C 分别继承 A 并且重写 function(),当创建一个对象 A b = new B(); b.function()就调用 B 的 funciotn,假如你 new C(),那调用的就是 C 重写的 function。虚拟机怎么判断你使用的是哪个类的 function 就是动态绑定,这个现象就是多态。


装载的第一步就是要获得二进制的字节流,它可以从读.class 文件获得,也可以从网络中接收别人发送的字节流。反正只要符合虚拟机规定的字节流格式都可以进入这个阶段。


有了字节流之后,要进行装载还需要一个工具,那就是加载器了。加载器既可以使用系统提供的引导类加载器,也可以使用用户自己定义的加载器,只需要继承 ClassLoader,再重写 loadClass()方法就可以实现一个自己的简单加载器。


像上面的代码那样,就是一个简单的类加载器。当我们要自己加载某个类的时候,就可自己调用 loadClass 方法,参数通常为要加载类的全类名,再根据 name 获得文件,得到字节流后便可加载,示例代码如下:

public class Test extends ClassLoader{	@Override	public Class<?> loaderClass(String name) throws ClassNotFoundException {		// 获得.class文件的名称		String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";		try {			InputStream is = new FileInputStream(fileName); // 获得字节流			if(is == null) { // 若为空,就调用父类加载器				return super.loadClass(name);			}			byte b[] = new byte[is.available()];			is.read(b); //将字节流全部读进字节数组			// 进入接下来的阶段			return defineClass(name, b, 0, b.length);		} catch (FileNotFoundException e) {			e.printStackTrace();		}	} catch (IOException e) {			e.printStackTrace();	}	return super.loadClass(name);}
复制代码

一般的工作情况下我们不会自己去实现加载器,都是采用系统默认的加载器。绝大部分 Java 程序都会使用到系统提供的以下 3 种加载器:

  • Bootstrap ClassLoader:启动类加载器。负责加载 JAVA_HOME/lib/里所有能被虚拟机识别的类(如:rt.jar)。无法被 Java 程序直接引用,由 C++实现,不是 ClassLoader 子类。

  • Extension ClassLoader:扩展类加载器。负责加载 java 平台中扩展功能的一些 jar 包,包括 JAVA_HOME/lib/ext/目录中的或 java.ext.dirs 系统变量指定目录下的所有类库。是 ClassLoad 的子类,开发者可以直接使用该加载器。

  • App ClassLoader:应用程序类加载器。负责加载 classpath 中指定的 jar 包及目录中 class。getSystemClassLoader()的返回值就是该加载器,开发者可以直接使用该加载器。



发布于: 刚刚阅读数: 3
用户头像

No Silver Bullet 2021.07.09 加入

岂曰无衣 与子同袍

评论

发布
暂无评论
JVM进阶(十四)——初识JAVA 类加载机制_Java_No Silver Bullet_InfoQ写作社区