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.ExtClassLoaderを継承する代わりにAppClassLoaderも説明する.
継承関係:
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;
        }
    }