分析AppClassLoader,ExtClassLoader 和URLClassLoader 的關係

分析AppClassLoader,ExtClassLoader 和URLClassLoader 的關係


測試代碼: 

class Hello
{
	public String str = "Hello World";
	public void fun()
	{
		System.out.println(str);
	}
}

public class Test
{
	public static void main(String[] args)
	{
		Hello hello = new Hello();
		hello.fun();
		
		System.out.println("----------------------");
		
		//Hello類的類加載器
		ClassLoader classLoaderOfHello = Hello.class.getClassLoader();
		
		System.out.println("Hello is Loaded by : "+classLoaderOfHello);
		
		System.out.println("----------------------");
		
		//Hello類的類加載器的Class對象
		Class AppClazz = classLoaderOfHello.getClass();
		
		//分析Hello類的類加載器的Class對象的類繼承關係
		while(AppClazz != null)
		{
			System.out.println(AppClazz);
			
			AppClazz = AppClazz.getSuperclass();
		}
		
		System.out.println("----------------------");
		
		//取得擴展器加載器的類對象Class
		Class ExtClazz = classLoaderOfHello.getParent().getClass();
		
		while(ExtClazz != null)
		{
			System.out.println(ExtClazz);
			
			ExtClazz = ExtClazz.getSuperclass();
		}
	}
}




結論:

1.  用戶自定義的類是由 應用(系統)類加載器AppClassLoader加載

2.  在”父親委託機制”中,擴展類加載器ExtClassLoader是AppClassLoader的父親.

3.  AppClassLoader 和 ExtClassLoader 都擴展於 URLClassLoader加載器.

4.  也同時說明AppClassLoader而非繼承ExtClassLoader.


繼承關係:

java.lang.Object

       --- java.lang.ClassLoader
              --- java.security.SecureClassLoader
                      ---  java.net.URLClassLoader
                            --- sun.misc.Launcher$ExtClassLoader



java.lang.Object

       --- java.lang.ClassLoader
              --- java.security.SecureClassLoader
                      ---  java.net.URLClassLoader
                            --- sun.misc.Launcher$AppClassLoader



其實很簡單嘛,直接看AppClassLoader的源代碼就可以了嘛,哈哈,終於找到了好東東,上

JDK7: http://download.java.net/openjdk/jdk7/

JDK6: http://download.java.net/openjdk/jdk6/

下載其源代碼就可以了

現在直接來看其源代碼:


/**
     * The class loader used for loading from java.class.path.
     * runs in a restricted security context.
     */
    static class AppClassLoader extends URLClassLoader {

        static {
            ClassLoader.registerAsParallelCapable();
        }

        public static ClassLoader getAppClassLoader(final ClassLoader extcl)
            throws IOException
        {
            final String s = System.getProperty("java.class.path");
            final File[] path = (s == null) ? new File[0] : getClassPath(s);

          
            return AccessController.doPrivileged(
                new PrivilegedAction<AppClassLoader>() {
                    public AppClassLoader run() {
                    URL[] urls =
                        (s == null) ? new URL[0] : pathToURLs(path);
                    return new AppClassLoader(urls, extcl);
                }
            });
        }

        /*
         * Creates a new AppClassLoader
         */
        AppClassLoader(URL[] urls, ClassLoader parent) {
            super(urls, parent, factory);
        }

        /**
         * Override loadClass so we can checkPackageAccess.
         */
        public Class loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
            int i = name.lastIndexOf('.');
            if (i != -1) {
                SecurityManager sm = System.getSecurityManager();
                if (sm != null) {
                    sm.checkPackageAccess(name.substring(0, i));
                }
            }
            return (super.loadClass(name, resolve));
        }

        /**
         * allow any classes loaded from classpath to exit the VM.
         */
        protected PermissionCollection getPermissions(CodeSource codesource)
        {
            PermissionCollection perms = super.getPermissions(codesource);
            perms.add(new RuntimePermission("exitVM"));
            return perms;
        }

        /**
         * This class loader supports dynamic additions to the class path
         * at runtime.
         *
         * @see java.lang.instrument.Instrumentation#appendToSystemClassPathSearch
         */
        private void appendToClassPathForInstrumentation(String path) {
            assert(Thread.holdsLock(this));

            // addURL is a no-op if path already contains the URL
            super.addURL( getFileURL(new File(path)) );
        }

        /**
         * create a context that can read any directories (recursively)
         * mentioned in the class path. In the case of a jar, it has to
         * be the directory containing the jar, not just the jar, as jar
         * files might refer to other jar files.
         */

        private static AccessControlContext getContext(File[] cp)
            throws java.net.MalformedURLException
        {
            PathPermissions perms =
                new PathPermissions(cp);

            ProtectionDomain domain =
                new ProtectionDomain(new CodeSource(perms.getCodeBase(),
                    (java.security.cert.Certificate[]) null),
                perms);

            AccessControlContext acc =
                new AccessControlContext(new ProtectionDomain[] { domain });

            return acc;
        }
    }

哈,看了AppClassLoader的源代碼後,大家明白了吧,AppClassLoader 繼承了URLClassLoader,而且構造函數是直接調用URLClassLoader的構造

函數,loadClass(String name, boolean resolve)方法只是簡單做了包的安全檢查,然後就調用ClassLoader的 loadClass(String name, boolean resolve)方法了,其它的話,也是差不多..所以其功能和URLClassLoader差不多...


在ExtClassLoader也差不多,大家看看源代碼就明瞭的:

  /*
         * Creates a new ExtClassLoader for the specified directories.
         */
        public ExtClassLoader(File[] dirs) throws IOException {
            super(getExtURLs(dirs), null, factory);
        }

        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;
        }

        private static URL[] getExtURLs(File[] dirs) throws IOException {
            Vector<URL> urls = new Vector<URL>();
            for (int i = 0; i < dirs.length; i++) {
                String[] files = dirs[i].list();
                if (files != null) {
                    for (int j = 0; j < files.length; j++) {
                        if (!files[j].equals("meta-index")) {
                            File f = new File(dirs[i], files[j]);
                            urls.add(getFileURL(f));
                        }
                    }
                }
            }
            URL[] ua = new URL[urls.size()];
            urls.copyInto(ua);
            return ua;
        }

        /*
         * Searches the installed extension directories for the specified
         * library name. For each extension directory, we first look for
         * the native library in the subdirectory whose name is the value
         * of the system property <code>os.arch</code>. Failing that, we
         * look in the extension directory itself.
         */
        public String findLibrary(String name) {
            name = System.mapLibraryName(name);
            URL[] urls = super.getURLs();
            File prevDir = null;
            for (int i = 0; i < urls.length; i++) {
                // Get the ext directory from the URL
                File dir = new File(urls[i].getPath()).getParentFile();
                if (dir != null && !dir.equals(prevDir)) {
                    // Look in architecture-specific subdirectory first
                    // Read from the saved system properties to avoid deadlock
                    String arch = VM.getSavedProperty("os.arch");
                    if (arch != null) {
                        File file = new File(new File(dir, arch), name);
                        if (file.exists()) {
                            return file.getAbsolutePath();
                        }
                    }
                    // Then check the extension directory
                    File file = new File(dir, name);
                    if (file.exists()) {
                        return file.getAbsolutePath();
                    }
                }
                prevDir = dir;
            }
            return null;
        }

        private static AccessControlContext getContext(File[] dirs)
            throws IOException
        {
            PathPermissions perms =
                new PathPermissions(dirs);

            ProtectionDomain domain = new ProtectionDomain(
                new CodeSource(perms.getCodeBase(),
                    (java.security.cert.Certificate[]) null),
                perms);

            AccessControlContext acc =
                new AccessControlContext(new ProtectionDomain[] { domain });

            return acc;
        }
    }



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