今天看Java代理的一些文章的时候,通过动态代理想到了反射的问题,然后就想到了以前面试的时候被问到的一个面试问题: Class.forName与ClassLoader的区别? ,自己当时虽然回答上来了,但是回答的并不具体,今天有空做个整理。
在Java中Class.forName()和ClassLoader都是对类进行加载,我们也知道在Class.forName中会加载静态代码块,但是ClassLoader并不会加载静态代码块。
从以上我们也可以推出来,其实ClassLoader是遵循了双亲委派模型,最终会调用类加载器来加载,它的功能是 通过一个类的类名来获取该类的二进制字节流 , 然后将该字节流放入到JVM中 。 我们可以查看Class.forName的源码:
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
在以上的源码中可以看到最终是调用forName0这个方法,这个方法中有四个参数:
第一个参数:类名 第二个参数:是否对类进行初始化,设置为true,则会执行类中的静态代码块 第三个参数:第三个参数是设定类加载器 因此我们可以使用 Class.forName(String name, boolean initialize,ClassLoader loader) ,来自己设定是否进行初始化以及类加载器。
对于ClassLoader来说,Java中有三种ClassLoader,分别是:
BootstrapClassLoader
ExtClassLoader
AppClassLoader
而在ClassLoader源码中,主要是这 三种类加载器通过类的路径来加载该类生成二进制字节流放入JVM中 。
/*
* The class loader used for loading installed extensions.
*/
static class ExtClassLoader extends URLClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
/**
* create an ExtClassLoader. The ExtClassLoader is created
* within a context that limits which files it can read
*/
public static ExtClassLoader getExtClassLoader() throws IOException
{
final File[] dirs = getExtDirs();
try {
// Prior implementations of this doPrivileged() block supplied
// aa synthesized ACC via a call to the private method
// ExtClassLoader.getContext().
return AccessController.doPrivileged(
new PrivilegedExceptionAction<ExtClassLoader>() {
public ExtClassLoader run() throws IOException {
int len = dirs.length;
for (int i = 0; i < len; i++) {
MetaIndex.registerDirectory(dirs[i]);
}
return new ExtClassLoader(dirs);
}
});
} catch (java.security.PrivilegedActionException e) {
throw (IOException) e.getException();
}
}
private static File[] getExtDirs() {
String s = System.getProperty("java.ext.dirs");
File[] dirs;
if (s != null) {
StringTokenizer st =
new StringTokenizer(s, File.pathSeparator);
int count = st.countTokens();
dirs = new File[count];
for (int i = 0; i < count; i++) {
dirs[i] = new File(st.nextToken());
}
} else {
dirs = new File[0];
}
return dirs;
}
......
}
那么哪些地方使用到了Class.forName或者ClassLoader呢?
在进行JDBC连接时,我们通常使用Class.forName去实现。 在Spring中的IOC使用ClassLoader。 以上就是对Class.forName以及ClassLoader的整理!!