`
Vikings825
  • 浏览: 65248 次
  • 性别: Icon_minigender_1
  • 来自: 威海
文章分类
社区版块
存档分类
最新评论

Java ClassLoader

阅读更多
自己写写对Java ClassLoader的理解,

首先ClassLoader分为:
Bootstrap ClassLoader/启动类加载器
    主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作。
Extension ClassLoader/扩展类加载器
    主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作。
System ClassLoader/系统类加载器
    主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作。
User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
    在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性。

关系如下:

具体类的实现关系如下:


自定义类加载器加载一个类的步骤步骤,使用的双亲委托加载模式:


为什么要使用这种双亲委托模式呢?

    因为这样可以避免重复加载,当父亲已经加载了该类的时候,就没有必要子ClassLoader再加载一次。
    考虑到安全因素,我们试想一下,如果不使用这种委托模式,那我们就可以随时使用自定义的String来动态替代java核心api中定义类型,这样会存在非常大的安全隐患,而双亲委托的方式,就可以避免这种情况,因为String已经在启动时被加载,所以用户自定义类是无法加载一个自定义的ClassLoader。

下面写一段代码用于观察其加载过程:
public class ClassLoaderTree {

	public static void main(String[] args) {
		ClassLoader loader = ClassLoaderTree.class.getClassLoader();
		while (loader != null) {
			System.out.println(loader.toString());
			loader = loader.getParent();
		}
		}
}


结果观察一下,看看是不是跟想的一样。

上网去查classloader的资料,都叫我们自己如果要自定义classloader用于加载的类话,就只需重写findclass就行了,为什么了?自己看看了ClassLoader源码后,写了一个简易版的,很好理解。
import java.util.Hashtable;
import java.io.FileInputStream;

public class SimpleClassLoader extends ClassLoader {
    private Hashtable classes = new Hashtable();

    public SimpleClassLoader() {
    }

    /**
     * 
     * 函数用于查找返回自定义class文件的二进制文件
     */
    private byte findclass(String className)[] {
    	System.out.println("        >>>>>> 查找 返回类 "+className);
    	byte result[];
    	try {
    	    FileInputStream fi = new FileInputStream("store\\"+className+".impl");
    	    result = new byte[fi.available()];
    	    fi.read(result);
    	    return result;
    	} catch (Exception e) {

    	    /*
    	     * If we caught an exception, either the class wasnt found or it
    	     * was unreadable by our process.
    	     */
    	    return null;
    	}
    }

    /**
     * loadClass 用于加载类(根据类名字符串)
     */
    public Class loadClass(String className) throws ClassNotFoundException {
        return (loadClass(className, true));
    }

    /**
     * 加载类的具体过程
     */
    public synchronized Class loadClass(String className, boolean resolveIt)
    	throws ClassNotFoundException {
        Class result;
        byte  classData[];

        System.out.println("        >>>>>>加载 class : "+className);

        /* Check our local cache of classes */
        result = (Class)classes.get(className);
        if (result != null) {
            System.out.println("        >>>>>> 返回已经加载的class.");
            return result;
        }

        /* Check with the primordial class loader */
        try {
            result = super.findSystemClass(className);
            System.out.println("        >>>>>> 从CLASSPATH中返回已经加载的类");
            return result;
        } catch (ClassNotFoundException e) {
            System.out.println("        >>>>>> CLASSPATH中没有这个类.");
        }

        /* 自定读取class */
        classData = findclass(className);
        if (classData == null) {
            throw new ClassNotFoundException();
        }

        /* 定义类 (分析 class 文件) */
        result = defineClass(classData, 0, classData.length);
        if (result == null) {
            throw new ClassFormatError();
        }

        if (resolveIt) {
            resolveClass(result);//解析class文件
        }

        classes.put(className, result);
        System.out.println("        >>>>>> 返回 这个新加载 class.");
        return result;
    }
}



  • 大小: 14.1 KB
  • 大小: 30.8 KB
  • 大小: 24.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics