`
zy19982004
  • 浏览: 654996 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
F6f66edc-1c1a-3859-b76b-a22e740b7aa7
Hadoop学习
浏览量:250062
社区版块
存档分类
最新评论

Java ClassLoader学习一:Launcher源码

 
阅读更多

一.Launcher

     我们习以为常的ClassLoader.getSystemClassLoader()来获得系统类加载器,有没有考虑过到底是怎么得到的呢?阅读完Launcher的源码,就清楚了。

 

二.源码

public class Launcher {
    private static URLStreamHandlerFactory factory = new Factory();
    private static Launcher launcher = new Launcher();

    public static Launcher getLauncher() {
        return launcher;
    }

    private ClassLoader loader;
    
    //ClassLoader.getSystemClassLoader会调用此方法
    public ClassLoader getClassLoader() {
    	return loader;
    }

    public Launcher() {
        // 1. 创建ExtClassLoader 
        ClassLoader extcl;
        try {
            extcl = ExtClassLoader.getExtClassLoader();
        } catch (IOException e) {
            throw new InternalError(
                "Could not create extension class loader");
        }

        // 2. 用ExtClassLoader作为parent去创建AppClassLoader 
        try {
            loader = AppClassLoader.getAppClassLoader(extcl);
        } catch (IOException e) {
            throw new InternalError(
                "Could not create application class loader");
        }

        // 3. 设置AppClassLoader为ContextClassLoader
        Thread.currentThread().setContextClassLoader(loader);
        //...
    }

    static class ExtClassLoader extends URLClassLoader {
        private File[] dirs;

        public static ExtClassLoader getExtClassLoader() throws IOException
        {
            final File[] dirs = getExtDirs();
            return new ExtClassLoader(dirs);
        }

        public ExtClassLoader(File[] dirs) throws IOException {
            super(getExtURLs(dirs), null, factory);
            this.dirs = dirs;
        }

        private static File[] getExtDirs() {
            String s = System.getProperty("java.ext.dirs");
            File[] dirs;
            //...
            return dirs;
        }
    }

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

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

            URL[] urls = (s == null) ? new URL[0] : pathToURLs(path);
            return new AppClassLoader(urls, extcl);
        }

        AppClassLoader(URL[] urls, ClassLoader parent) {
            super(urls, parent, factory);
        }
        
        /**
         * Override loadClass so we can checkPackageAccess.
         * 这个方法似乎没什么必要,因为super.loadClass(name, resolve)时也会checkPackageAccess
         */
        public synchronized 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));
        }

    }
}

 

 

三.源码说明

  1. Launcher源码里定义了static的扩展类加载器ExtClassLoader, static的系统类加载器AppClassLoader。
  2. 它们都是默认包级别的,它们都是继承URLClassLoader,这就意味着我们的代码里,不能定义ExtClassLoader laoder = ...或AppClassLoader loader = ...。我们只能ClassLoader loader = ...,而在实际运行时,我们应当能辨别这个loader到底是哪个具体类型。
  3. 在ExtClassLoader构造器里,并没有指定parent,或者说ExtClassLoader的parent为null。因为ExtClassLoader的parent是BootstrapLoader,而BootstrapLoader不存在于Java Api里,只存在于JVM里,我们是看不到的,所以请正确理解"ExtClassLoader的parent为null"的含义。
  4. 在AppClassLoader构造器里,有了parent。实例化AppClassLoader的时候,传入的parent就是一个ExtClassLoader实例。
  5. 看看Launcher的构造方法。
      1. 先实例化ExtClassLoader,从java.ext.dirs系统变量里获得URL[]。
      2. 用这个ExtClassLoader作为parent去实例化AppClassLoader,从java.class.path系统变量里获得URL[]。Launcher getClassLoader()就是返回的这个AppClassLoader。
      3. 设置AppClassLoader为ContextClassLoader。

四.例子

 

package com.jyz.study.jdk.classLoader;

import java.net.URL;

import sun.misc.Launcher;

/**
 * 演示
 * appClassLoader
 * extClassloader
 * bootstrapLoader
 * 所加载的文件
 * @author JoyoungZhang@gmail.com
 * 
 */
public class ClassLoaderTest {
	public static void main(String[] args) throws Exception {
		
		ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
		ClassLoader extClassloader = appClassLoader.getParent();
		ClassLoader bootstrapLoader  = extClassloader.getParent();
		System.out.println("the bootstrapLoader : " + bootstrapLoader);
		System.out.println("the extClassloader : " + extClassloader);
		System.out.println("the appClassLoader : " + appClassLoader);
		
		System.out.println();
		System.out.println("bootstrapLoader加载以下文件:");
		URL[] urls = Launcher.getBootstrapClassPath().getURLs();
		for (int i = 0; i < urls.length; i++) {
		    System.out.println(urls[i]);
		}
		
		System.out.println();
		System.out.println("extClassloader加载以下文件:");
		System.out.println(System.getProperty("java.ext.dirs"));
		
		System.out.println();
		System.out.println("appClassLoader加载以下文件:");
		System.out.println(System.getProperty("java.class.path"));
		
	}
}



console output:
the bootstrapLoader : null
the extClassloader : sun.misc.Launcher$ExtClassLoader@1c78e57
the appClassLoader : sun.misc.Launcher$AppClassLoader@6b97fd

bootstrapLoader加载以下文件:
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/resources.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/rt.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/sunrsasign.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/jsse.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/jce.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/charsets.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/lib/modules/jdk.boot.jar
file:/C:/Program%20Files/Java/jdk1.6.0_27/jre/classes

extClassloader加载以下文件:
C:\Program Files\Java\jdk1.6.0_27\jre\lib\ext;C:\Windows\Sun\Java\lib\ext

appClassLoader加载以下文件:
E:\GoogleCode\platform-components\trunk\SourceCode\study-jdk\target\classes;E:\GoogleCode\platform-components\trunk\SourceCode\component-core\target\classes;C:\Users\audaque\.m2\repository\junit\junit\3.8.1\junit-3.8.1.jar

 

 

 

1
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics