类加载器 ClassLoader

本贴最后更新于 1680 天前,其中的信息可能已经时移世易

类加载器概述

 主要的作用是将 class 文件加载到 jvm 虚拟机中。jvm 启动的时候,并不是一次性加载所有的类,而是根据需要动态去加载类,主要分为隐式加载和显示加载。

  1. 隐式加载:
    程序代码中不通过调用 ClassLoader 来加载需要的类,而是通过 JVM 类自动加载需要的类到内存中。例如,当我们在类中继承或者引用某个类的时候,JVM 在解析当前这个类的时,发现引用的类不在内存中,那么就会自动将这些类加载到内存中。

  2. 显示加载:
    代码中通过 Class.forName(),this.getClass.getClassLoader.LoadClass(),自定义类加载器中的 findClass()方法等。

加载机制

Java 默认提供的三个 ClassLoader

  1. BootStrap ClassLoader:
    主要加载 %JRE_HOME%\lib 下的 rt.jar、resources.jar、charsets.jar 和 class 等。
    可以通过 System.getProperty("sun.boot.class.path")查看加载路径
  2. EtxClassLoader
    主要加载目录 %JRE_HOME%\lib\ext 目录下的 jar 包和 class 文件。
    可以通过 System.out.println(System.getProperty("java.ext.dirs"))查看加载路径
  3. AppClassLoader
    主要加载当前应用下的 classpath 路径下的类。之前我们在环境变量中配置的 classpath 就是指定 AppClassLoader 的类加载路径。

类加载器的继承关系

image

双亲委派模式

image

双亲委派模式指 ClassLoader 会先交由父加载器加载,由上而下依次检查,如最后自己也找不到类,则抛出 ClassNotFoundException 异常

双亲委派的好处

带有层级关系,可避免重复加载

自定义类加载器

当 class 文件不在上述加载器的目录范围内是,则使用自定义加载器

package test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader{

    private String classpath;
    
    public MyClassLoader(String classpath) {
        
        this.classpath = classpath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte [] classDate=getDate(name);
            
            if(classDate==null){}
            
            else{
                //defineClass方法将字节码转化为类
                return defineClass(name,classDate,0,classDate.length);
            }
            
        } catch (IOException e) {
            
            e.printStackTrace();
        }
        
        return super.findClass(name);
    }
    //返回类的字节码
    private byte[] getDate(String className) throws IOException{
        InputStream in = null;
        ByteArrayOutputStream out = null;
        String path=classpath + File.separatorChar +
                    className.replace('.',File.separatorChar)+".class";
        try {
            in=new FileInputStream(path);
            out=new ByteArrayOutputStream();
            byte[] buffer=new byte[2048];
            int len=0;
            while((len=in.read(buffer))!=-1){
                out.write(buffer,0,len);
            }
            return out.toByteArray();
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        finally{
            in.close();
            out.close();
        }
        return null;
    }
}
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...