Java的类加载器
时间:2022-07-24
本文章向大家介绍Java的类加载器,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
作用
- 编译器先把java文件编译成class字节码文件
- ClassLoad会把字节码文件转换成jvm中的Class对象
- jvm再把class对象转成实例对象
ClassLoad在java 中有着非常重要的作用,他主要工作是在Class装载的加载过程,他的主要作用是 从系统外部获取二进制数据流。它是java的核心组件,所有的class都是通过ClassLoad进行加载的,ClassLoad负责将class文件里的二进制流输入到系统中交给jvm进行连接,初始化操作。
分类
- 系统自带的类加载器
- 启动类加载器(BootStrap) c++编写 加载核心库 java.* 3.拓展类加载器 (Extension) java编写 加载拓展库 javax.* 4.应用程序加载类(AppClassLoader)java编写 加载程序所在目录 5.用户自定义的类加载器 自定义类加载器 java编写 定制化加载
我们先了解2个方法
第一个方法 findClass
/**
* Finds the class with the specified <a href="#name">binary name</a>.
* This method should be overridden by class loader implementations that
* follow the delegation model for loading classes, and will be invoked by
* the {@link #loadClass <tt>loadClass</tt>} method after checking the
* parent class loader for the requested class. The default implementation
* throws a <tt>ClassNotFoundException</tt>.
*
* @param name
* The <a href="#name">binary name</a> of the class
*
* @return The resulting <tt>Class</tt> object
*
* @throws ClassNotFoundException
* If the class could not be found
*
* @since 1.2
*/
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
我大概翻译了一下:
将字节数组转换为类Class的实例。必须先解析Class才能使用。
大白话就是,将字节流转换为类,找不到就报错!子类应该覆盖这个方法 第二个方法 defineClass
protected final Class<?> defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
throws ClassFormatError
{
protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
根据其官方文档,再简化之后我总结了九个字:将字节数组转换为类
模拟一个类,假装这个类是外部文件!我们通过类加载器去加载这个文件!我们通过类加载器创建该实例!他就会打印构造函数中的一句话!废话不多说我们直接上图吧!
/**
* 模拟这个类被加载,我们先把他搞成.class文件 然后,他被加载时就会打印空构造方法!
*/
public class TestClasssLoader {
public TestClasssLoader() {
System.out.println("Hello ClasssLoader!!!");
}
}
在本地cmd命令行,通过javac TestClasssLoader.java 编译此文件,会得到一个.class文件,我们将这个class文件随便放个地方!然后开始编写我们自己的类加载器!
package com.zanzan.vo;
import lombok.AllArgsConstructor;
import java.io.*;
/**
* 自定义类加载器
* @author huangfu
* @AllArgsConstructor 是lombok一个插件,他就是生成MyClassLoader的构造方法的!你也可以手动生成
*/
@AllArgsConstructor
public class MyClassLoader extends ClassLoader {
/**
* .class文件所在位置
*/
private String path;
/**
* 查找类加载器
* @param name 类名(不带.class)
* @return
* @throws ClassNotFoundException
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = new byte[0];
try {
//这里就是为了获取.class文件的字节流
bytes = loadClassFile(name);
} catch (IOException e) {
e.printStackTrace();
}
/**
* 开始加载类
* 四个参数!
* 1.类的名称
* 2. .class文件的字节流
* 3. 从那个位置开始读取
* 4. 读取多长
*/
return defineClass(name,bytes,0,bytes.length);
}
/**
* 获取.class文件的字节流信息
* @param fileName
* @return
* @throws IOException
*/
private byte[] loadClassFile(String fileName) throws IOException {
String pathFile = path+File.separator+fileName+".class";
FileInputStream in = new FileInputStream(pathFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int readIndex = -1;
while ((readIndex = in.read())!=-1){
out.write(readIndex);
}
in.close();
out.close();
return out.toByteArray();
}
}
功能测试
终于,我们的代码写完了,我们需要测试一下功能!在测试之前回顾一下java的一个基础!类在被加载的时候,会自动调用空构造函数!所以我们的外部类,一旦被加载就会打印 HelloClasssLoader!!!
来吧,试一下吧!
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
MyClassLoader myClassLoader = new MyClassLoader("C:\Users\huangfu\Desktop");
Class<?> testClasssLoader = myClassLoader.findClass("TestClasssLoader");
testClasssLoader.newInstance();
}
结果:
Hello ClassLoader!!!
Process finished with exit code 0
搞定收工!赶紧回去试试吧!欢迎关注作者哦!
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 如何管理和组织一个机器学习项目
- Spring Web MVC 简单使用
- Spring 中的 JDBC
- IDEA 快键键:展开所有文件夹、折叠所有文件夹(自定义)
- mysql 数据库的悲观锁和乐观锁
- C语言 二维数组和指针的一些笔记
- Java SpringBoot2.3.4 配置redis 基于lettuce 同时支持集群与单机 配置密码加密 并使用redisson分布式锁
- 使用elasticsearch-dump迁移elasticsearch集群数据
- Python爬虫之scrapy的入门使用
- 告别传统工业互联网,提高数字管控思维:三维组态分布式能源站
- 爱奇艺iOS移动端网络优化实践:请求成功率优化
- Java数据类型
- Python爬虫之scrapy构造并发送请求
- Python爬虫之scrapy模拟登陆
- Python爬虫之scrapy中间件的使用