jvm一启动,就会开始做一些初始化的动作,之后就会产生一个BootStrapClassLoader,该ClassLoader由C++ native提供,他除了做一些基本的初始化,最重要的工作就是加载sun.misc.Launcher$ExtClassLoader,并设置其parent为null,接着加载sun.misc.Launcher$AppClassLoader,并将其parent设置为ExtClassLoader。
下面看一段ClassLoader中loadclass方法源码
———————————————————————————————————
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null)
{
try
{
if (parent != null)
{
c = parent.loadClass(name, false);
}
else
{
c = findBootstrapClass0(name);
}
}
catch (ClassNotFoundException e)
{
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve)
{
resolveClass(c);
}
return c;
}
——————————————————————————————————
通过以上源码,可以看到,ClassLoader会先看该类实行已经被加载,如果被加载则直接返回,否则去父加载器中查找,最后调用findClass方法查找该类,故如果我们想要实现自己的ClassLoader,关键点就在于重写findClass类。从此处联想到web应用中,web容器会去WEB-INF/classes下加载类,会去WEB-INF/lib下加载库,应该是web容器实现了WebAppClassLoader,并覆盖findClass方法,到指定路径下去寻找类库了。
记起每次在web应用中调用Clazz.class.getClassLoader().getResource()去取得资源文件时的困扰,一直不理解。现在看来,getResource传入一个资源的相对路径,该路径是相对WebAppClassLoader的类加载跟路径而言的,若传入".",则得到的就是该WebAppClassLoader类加载器的根路径。
Leave a Reply