java类加载

1.类加载器
1.BootStrapClassLoader 启动类加载器。加载rt.jar 以及 java. 开头的类。
2.ExtClassLoader 扩展类加载器。 Extent。加载 javax. 开头的类。
3.AppClassLoader 应用程序类加载器。加载 class文件下的类。
4.自定义加载器。

2.双亲委派模型
先判断该类的父加载器能否加载该类,若父类加载器能加载则交给父类加载器来加载,若父类无法加载,则自己加载。如果自己也不行,则抛ClassNotFoundException。双亲委派模型确保了内存中只有一份相同的字节码。不会重复加载多次。
每个class在加载的时候,会先判断缓存中是否已经加载过了该类,如果已经加载了,则直接从缓存中取。如果缓存中没有,jvm再到文件中取出二进制数据,转换成class加载到内存中。这也是为什么修改了class文件不起效果,需要重启jvm才可以。

 protected Class loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
image.png

AppClassLoader 加载classpath下的class。classpath主要包括两部分:一部分是 WEB-INF下的classes,一部分是WEB-INF下的lib。AppClassLoader继承UrlClassLoader,按照文件顺序来加载。所以一般先加载classes,在加载lib中的jar包。当发现有jar错误想调试时,可以在classes中创建一个相同包名类名的class,这样类加载器会加载这个类而不会加载jar包中的类。

你可能感兴趣的:(java类加载)