自定义类加载器[1]:突破父类委托机制

来源:互联网 发布:淘宝的规律 编辑:程序博客网 时间:2024/06/11 17:36

 

如果要突破父类委托机制,需要重写loadClass()方法。

如下的例子,当遇到某个类名的时候,会先自己尝试加载,如果自己加载不到,再交由父加载器加载。

 Java Code 

 

package com.bjsxt.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class CustomClassLoader extends ClassLoader {

    
private String rootDir;

    
public CustomClassLoader(String rootDir) {
        
this.rootDir = rootDir;
    }

    
// ClassLoader复制过来修改
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {//这里的ClassNotFoundException是有parent.loadClass()抛出的
        synchronized (getClassLoadingLock(name)) {

            
// 判断当前类加载器是否已经加载该类
            Class<?> c = findLoadedClass(name);

            
if (c == null) {// 未加载//尝试去加载

                c = findClass(name);

                
if (c == null) {//加载不到,交由父加载器去加载
                    ClassLoader parent = getParent();
                    
                    
if(parent!=null)
                        
return parent.loadClass(name);//here
                }

            } 
// 已经加载

            
if (resolve) {
                resolveClass(c);
            }
            
            
return c;
        }
    }

    @Override
    
protected Class<?> findClass(String name){
        
// 从自定义目录读取文件,转化为一个字节数组
        byte[] classData = loadClassBytes(name);

        
if (classData == null) {
            
// throw new ClassNotFoundException();
            //这个地方就不再抛出异常了
            System.out.println("CustomClassLoader cannot load "+name+", try parent.");
            
return null;
        } 
else {
            Class c = defineClass(name, classData, 
0, classData.length);
            
return c;
        }

    }

    
private byte[] loadClassBytes(java.lang.String name) {

        
String path = rootDir + "/" + name.replace(".""/") + ".class";

        InputStream is = null;
        ByteArrayOutputStream baos = null;

        
try {
            is = 
new FileInputStream(path);
            baos = 
new ByteArrayOutputStream();

            
byte[] buffer = new byte[1024];
            
int ret = 0;
            
while ((ret = is.read(buffer)) != -1) {
                baos.write(buffer, 
0, ret);
            }

            
return baos.toByteArray();

        } 
catch (FileNotFoundException e) {
            e.printStackTrace();
//这里输出FileNotFoundException
        } catch (IOException e) {
            e.printStackTrace();
        } 
finally {
            
try {
                
if (is != null)
                    is.close();

                
if (baos != null)
                    baos.close();
            } 
catch (IOException e) {
                e.printStackTrace();
            }
        }

        
return null;
    }
}

 

依然使用之前的HelloWorld.class来测试。


 

执行输出语句的时候,会遇到

java.lang.Object

java.lang.System

java.io.PrintStream

CustomClassLoader会先尝试加载,加载不到再交由父类加载器加载。(AppClassLoader,并回归正常机制。)

 

0 0