类加载器

参考《探秘Java9之类加载》:https://yq.aliyun.com/articles/518315

类加载器的组织结构

BootClassLoader
1、由C/C++语言编写的一个类。
2、启动类加载器,用于加载启动的基础模块类。

PlatformClassLoader
1、平台类加载器,用于加载一些平台相关的模块,双亲是BootClassLoade。
2、java语言编写

AppClassLoader
1、应用模块加载器,用于加载应用级别的模块(包含用户自定义的类),双亲是PlatformClassLoader。

加载器之间是上下级的关系,不是子父类的关系。

 Java9之前和Java9使用ClassLoader的方式对比:

package test;

import java.lang.reflect.InvocationTargetException;

public class ClassLoaderTest {

    public static void main(String[] args) {


        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        try {
            /** Java9之前的使用方式 */
            Class clazz = loader.loadClass("test.Car");
            Object obj = clazz.newInstance();
            Car car = (Car) obj;
            car.run();

        } catch (ClassNotFoundException e) {
            System.err.println(e);
        } catch (InstantiationException e) {
            System.err.println(e);
        } catch (IllegalAccessException e) {
            System.err.println(e);
        }

        try {
            /** Java9的使用方式 */
            Class clazz = loader.loadClass("test.Car");
            Object obj = clazz.getDeclaredConstructor(String.class).newInstance("Benz");
            Car car = (Car) obj;
            car.run();

        } catch (ClassNotFoundException e) {
            System.err.println(e);
        } catch (NoSuchMethodException e) {
            System.err.println(e);
        } catch (SecurityException e) {
            System.err.println(e);
        } catch (InstantiationException e) {
            System.err.println(e);
        } catch (IllegalAccessException e) {
            System.err.println(e);
        } catch (IllegalArgumentException e) {
            System.err.println(e);
        } catch (InvocationTargetException e) {
            System.err.println(e);
        }

    }
}

 

Car类:

package test;

public class Car {

    public Car(String brand) {
        this.brand = brand;
    }

    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public void run() {
        System.out.println("run....");
    }
}

 类加载器常用方法:

 class NetworkClassLoader extends ClassLoader {
         String host;
         int port;

         public Class findClass(String name) {
             byte[] b = loadClassData(name);
             return defineClass(name, b, 0, b.length);
         }

         private byte[] loadClassData(String name) {
             // load the class data from the connection
              . . .
         }
     }

 类加载器加载机制:双亲委托机制

- 如果一个类加载器收到了类加载的请求,
- 它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,
- 因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,
- 只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,
- 子加载器才会尝试自己去加载该类。

 

自定义类加载器

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class MyClassLoader extends ClassLoader{

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		String srcPath = args[0];
		String destDir = args[1];
		FileInputStream fis = new FileInputStream(srcPath);
		String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
		String destPath = destDir + "\\" + destFileName;
		FileOutputStream fos = new FileOutputStream(destPath);
		cypher(fis,fos);
		fis.close();
		fos.close();
	}
	
	private static void cypher(InputStream ips ,OutputStream ops) throws Exception{
		int b = -1;
		while((b=ips.read())!=-1){
			ops.write(b ^ 0xff);
		}
	}

	private String classDir;

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		// TODO Auto-generated method stub
		String classFileName = classDir + "\\"  + name.substring(name.lastIndexOf('.')+1) + ".class";
		try {
			FileInputStream fis = new FileInputStream(classFileName);
			ByteArrayOutputStream  bos = new ByteArrayOutputStream();
			cypher(fis,bos);
			fis.close();
			System.out.println("aaa");
			byte[] bytes = bos.toByteArray();
			return defineClass(bytes, 0, bytes.length);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public MyClassLoader(){
		
	}
	
	public MyClassLoader(String classDir){
		this.classDir = classDir;
	}
}

 调用自定义类加载器加载指定的类:

Class clazz = new MyClassLoader("类所在的文件夹名称,相对路径").loadClass("ClassLoaderAttachment");
//注意如果要加载的类与写这个语句的类在同一目录下,类名前要加包名,优先使用父加载器进行加载。
//如果是在当前工作目录下的一个文件夹里,可以直接写类名。此时父加载器找不到这个类,则会使用自定义的加载器进行加载。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值