Java ClassLoader 类加载器

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
      加载 就是指将class文件读入内存,并为之创建一个Class对象。 任何类被使用时系统都会建立一个Class对象。
       连接
            验证 是否有正确的内部结构,并和其他类协调一致
            准备 负责为类的静态成员分配内存,并设置默认初始化值(静态成员,类的创建而创建)
           解析 将类的二进制数据中的符号引用替换为直接引用
      初始化 就是我们以前讲过的初始化步骤



加载器

1. Bootstrap ClassLoader

负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

2. Extension ClassLoader

负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目录下的jar包

3. App ClassLoader

负责记载classpath中指定的jar包及目录中class

4. Custom ClassLoader

属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader

加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。


类的初始化

    类什么时候才被初始化:

1)创建类的实例,也就是new一个对象

2)访问某个类或接口的静态变量,或者对该静态变量赋值

3)调用类的静态方法

4)反射(Class.forName("com.lyj.load"))

5)初始化一个类的子类(会首先初始化子类的父类)

6)JVM启动时标明的启动类,即文件名和类名相同的那个类

         只有这6中情况才会导致类的类的初始化。


自定义加载器

public class CustomClassLoader extends ClassLoader {  
    // 要加载的类  
    private String name;  
    // 设置父加载器和需要加载的类
    public CustomClassLoader(ClassLoader parent , String name) {  
        super(parent);  
        if(name == null || name.length() <= 0)  
            throw new NullPointerException();  
        this.name = name;  
    }  
    // 重写加载器
    @Override  
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {  
        Class<?> clazz = null;  
        /**如果是我们想要热加载的类则调用我们重写的findClass方法来加载**/  
        if(this.name.equals(name) && !"java".equals(name)){  
        	// 调用系统加载class文件
            clazz = findLoadedClass(name);  
            if(clazz == null)  
            	// 调用自定义的
                clazz = findClass(name);  
  
            // 类的生命周期包括:加载、验证、准备、解析、初始化、使用、卸载。其中验证、准备、解析统称为连接 
            //如果类已连接过,resolveClass方法会直接返回  
            if(resolve)  
                resolveClass(clazz);
            return clazz;  
        }  
        // 调用父加载器
        return super.loadClass(name , resolve);  
    }  
  
    @Override  
    protected Class<?> findClass(String name) throws ClassNotFoundException {  
    	// 获得实际存储class文件位置
        String fileName = c2f(name);
        // 读取class文件
        byte[] bytes = f2b(fileName);  
        // 根据class文件生成Class类对象
        return defineClass(name, bytes, 0, bytes.length);  
    }  
  
    // 类名转为文件名 
    private String c2f(String name){  
        /**编译后的class文件存放的目录**/  
        String baseDir = "F:\\classes";  
        name = name.replace("." , File.separator);  
        name = baseDir + name + ".class";  
        return name;  
    }  
  
    // 读取文件byte数组 
    private byte[] f2b(String fileName){  
        RandomAccessFile file = null;  
        FileChannel channel = null;  
        byte[] bytes = null;  
        try {  
            /**随机存取文件对象,只读取模式**/  
            file = new RandomAccessFile(fileName , "r");  
            /**NIO文件通道**/  
            channel = file.getChannel();  
            /**NIO字节缓冲**/  
            ByteBuffer buffer = ByteBuffer.allocate(1024);  
            int size = (int) channel.size();  
            bytes = new byte[size];  
            int index = 0;  
            /**从NIO文件通道读取数据**/  
            while (channel.read(buffer) > 0){  
                /**字节缓冲从写模式转为读取模式**/  
                buffer.flip();  
                while (buffer.hasRemaining()){  
                    bytes[index] = buffer.get();  
                    ++index;  
                }  
                /**字节缓冲的readerIndex、writerIndex置零**/  
                buffer.clear();  
            }  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }finally {  
            if (channel != null) {  
                try {  
                    channel.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
            if (file != null) {  
                try {  
                    file.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        }  
        return bytes;  
    }  
  
    // 加载 
    public Class<?> loadClass(){  
        try {  
        	// 调用系统loadClass(name,false)
            return loadClass(name);  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
            return null;  
        }  
    }  
}  


public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException {
		
	String name = "top.xfdtm.test.Person";

	CustomClassLoader loader = new CustomClassLoader(Thread.currentThread()
				.getContextClassLoader(), name);
	Class<?> clazz = loader.loadClass();
	Object obj = clazz.newInstance();
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值