Java基础——类加载机制

类加载概念:
每个Java文件经过Java编译器编译成拓展名为”.class”的文件,”.class”文件中保存着Java代码经转换后的虚拟机指令,当需要使用某个类时,虚拟机将会加载它的”.class”文件,并创建对应的class对象,将class文件加载到虚拟机的内存,这个过程称为类加载。
这里写图片描述

1、如何识别.class文件?
这里写图片描述

2、识别到对应的class文件后,该如何加载它?依赖加载器?

类加载器分为三种:
启动类加载器(Bootstrap classLoader):又称为引导类加载器,由C++编写,无法通过程序得到。主要负责加载JAVA中的一些核心类库,主要是位于/lib/rt.jar中。

拓展类加载器(Extension classLoader):主要加载JAVA中的一些拓展类,位于/lib/ext中,是启动类加载器的子类。

应用类加载器(System classLoader): 又称为系统类加载器,主要用于加载CLASSPATH路径下我们自己写的类,是拓展类加载器的子类。
这里写图片描述

这里写图片描述
寻找类加载器实例:

public class ClassLoaderTest { 
public static void main(String[] args) { 
ClassLoader loader = Thread.currentThread().getContextClassLoader(); System.out.println(loader);
System.out.println(loader.getParent()); 
System.out.println(loader.getParent().getParent()); 
  }
 }

运行输出结果:

sun.misc.Launcher$AppClassLoader
@64fef26a
sun.misc.Launcher$ExtClassLoader
@1ddd40f3
null

3、双亲委派模型
双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。

 protected Class<?> loadClass(String name, boolean resolve)    
    throws ClassNotFoundException    
{    
    synchronized (getClassLoadingLock(name)) {    

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

            }    
p;                //父类没加载成功    
            if (c == null) {    

                long t1 = System.nanoTime();    
                c = findClass(name);    


                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);    
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);    
                sun.misc.PerfCounter.getFindClasses().increment();    
            }    
        }    
        if (resolve) {    
            resolveClass(c);    
        }    
        return c;    
    }     

这段代码实现了双亲委派模式。
双亲委派模型意义:

-系统类防止内存中出现多份同样的字节码

扫描二维码关注公众号,回复: 2291055 查看本文章

-保证Java程序安全稳定运行

4、类加载的三种方式:

loadClass:负责以双亲委派方式去加载类。
findClass:根据类的包路径找到class文件。
defindClass:负责从class字节码中加载Class对象,然后Class对象通过反射机 制才生成对象的。

递归是去把请求委派给父类加载器时调用loadClass()方法,加载时调用findClass方法。

当我们去写自己的自定义类加载器时,不用每次都重写 loadClass 方法,这样会破坏它的双亲委派机制,只需要重写 findClass方法就好了。

猜你喜欢

转载自blog.csdn.net/qq_41930448/article/details/80587486