前言
今天看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的整理!!