Class.forName與ClassLoader的區別 前言

前言

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

來源:https://www.tuicool.com/articles/aQ3M7bn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章