自定义类加载器的实现

杂谈 专栏收录该内容
18 篇文章 0 订阅

Java的类加载器自从JDK1.2开始便引入了一条机制,叫做父类委托机制。也就是说,一个类需要被加载的时候,

JVM先会调用他的父类加载器进行加载。如果父类加载器加载不了,再使用其子类进行加载。当然,这类所说的父类加

载器,不一定他们之间是继承的关系,有可能仅仅是包装的关系。不能片面理解。

Java之所以出现这条机制,因为是处于安全性考虑。害怕用户自己定义class文件然后自己写一个类加载器来加载

原本应该是JVM自己加载的类。这样会是JVM虚拟机混乱或者说会影响到用户的安全。

下面我们来自己实现一个类加载器,其中主要就是继承ClassLoader类

package com.bird.classLoad;


import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {

	private String name; // 类加载器的名字

	private String path = "d://"; // 加载类的路径

	private final String fileType = ".class"; // .class文件扩展名

	public MyClassLoader(String name) {
		super();// 让系统加载器成为该类的加载器的父类加载器

		this.name = name;
	}

	public MyClassLoader(ClassLoader parent, String name) {
		super(parent); // 显示指定该类加载器的父加载器
		this.name = name;
	}

	@Override
	public String toString() {
		return this.name;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}
	
	/**
	 * 读取class文件作为二进制流放入到byte数组中去
	 * @param name
	 * @return
	 */
	private byte[] loadClassData(String name) {
		InputStream in = null;
		byte[] data = null;
		ByteArrayOutputStream baos = null;

		try {
			name = name.replace(".", "\\");
			in = new BufferedInputStream(new FileInputStream(new File(path
					+ name + fileType)));
			baos = new ByteArrayOutputStream();
			int ch = 0;
			while (-1 != (ch = in.read())) {
				baos.write(ch);
			}
			data = baos.toByteArray();
		} catch (Exception e) {

			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					baos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return data;
	}
	
	/**
	 * JVM调用的加载器的方法
	 */

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] data = this.loadClassData(name);
		return this.defineClass(name, data, 0, data.length);
	}
	
	public static void main(String[] args) throws Exception {
		MyClassLoader loader1 = new MyClassLoader("loader1");
		loader1.setPath("d://");
		test(loader1);
	}
	
	public static void test(ClassLoader loader) throws Exception{
		Class<?> clazz = loader.loadClass("com.bird.classLoad.Simple");
		Object object = clazz.newInstance();
	}

}

protected Class<?> findClass(String name) 这个方法是JVM自己调用的,如果覆盖CLassLoader类,必须覆盖这个方

法才能实现类的加载。然后里面的private byte[] loadClassData(String name) 方法是加载class文件变成二进制文件,

以便加载器完成class的引用。

  • 4
    点赞
  • 4
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

打赏
文章很值,打赏犒劳作者一下
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏

Bird

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值