java 类加载过程

class文件的加载主要分为3个步骤:

  1. Loading
  2. Linking (Verification -----> Preparation -----> Resolution)
  3. Initializing
Loading

Loading是指把class文件从硬盘加载到内存。

Linking

Linking(链接)又分为3小步:
① Verification(验证)主要做一些基础验证,包括文件是否符合class文件的标准等(模数验证)
② Preparation (准备)主要是给class文件中静态变量赋默认值
③ Resolution 将类、方法、属性等符号引用解析为直接引用,常量池中的各种符号引用解析为指针、偏移量等内存地址的直接引用。

Initializing

Initializing 初始化,把静态变量赋值为初始值(调用静态代码块)。

类加载器

classloader(类加载器)
class文件被加载到内存以后主要包括两块内容,class文件本身的二进制码以及该二进制码对应的Class对象。
java类加载器主要包括BootstarpClassLoader、ExtensionClassLoader、ApplicationClassLoader以及自定义类加载器。
BootstarpClassLoader(根加载器),由C++实现,加载jdk核心jar,例如lib/rt.jar、charset.jar等核心类,通过class.getClassLoader()方法获取到的值为null。
ExtensionClassLoader(扩展类记载器),主要加载扩展jar包,如jre/lib/ext/*.jar,也可以通过-Djava.ext.dirs指定。
ApplicationClassLoader(引用类加载器),加载classpath指定的内容(自己写的class文件)。

双亲委派

java的类加载机制被称为双亲委派,即一个class的加载首先由自定义类记载器(如果有的话)去自己的缓存中看看该类是否被加载,如果存在则证明该类已经被加载,如果不存在则委托自己的父加载器(application classLoader)尝试加载,父加载器可以通过getParent()方法获取。父加载器的加载过程也是一样,先确认自己的缓存中该类是否已经被加载,存在了这直接返回结果,不存在则委托自己的父加载器(extension classLoader)进行加载。如果在此过程中依然没有,则该加载类的请求会被委托到达bootstrap classLoader,根加载器依然是先查看自己是否加载过该类,如果没有则从固定路径进行加载,加载不成功则返回让extension classLoader尝试加载,extension classLoader加载不成功则通知application classLoader尝试加载,如果依然不成功,则由自定义类加载器进行加载,加载成功则返回结果,依然加载失败则抛出ClassNotFoundException。注意:各加载器之间不存在直接的继承关系,父加载器不是加载器的加载器,也不是类加载器的父类加载器。
之所以累的加载过程相对复杂,其原因在于通过双亲委派机制可以:

  1. 保证安全性。
  2. 保证一个类只会被加载一次。
    自定义类加载器
    自定义类加载器只需要extends ClassLoader覆盖findClass方法:
public class CustomClassLoader extends ClassLoader {

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        if (name == null || name.length() <= 0) {
            return null;
        }
        String filePath = "D:\\code\\learn\\classloader\\target\\classes" + name.replace(".", "\\").concat(".class");
        File file = new File(filePath);
        try (FileInputStream in = new FileInputStream(file);
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            int b;
            while ((b = in.read()) != 0) {
                out.write(b);
            }

            final byte[] bytes = out.toByteArray();

            return defineClass(name, bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }

    public static void main(String[] args) throws Exception {
        String name = "com.info.classloader.ClassExample";
        CustomClassLoader classLoader = new CustomClassLoader();
        final Class<?> aClass = classLoader.loadClass(name);
        final ClassExample example = (ClassExample) aClass.newInstance();
        example.method();
        System.out.println(example.getClass().getClassLoader());
        System.out.println(classLoader.getClass().getClassLoader());
        System.out.println(classLoader.getClass().getClassLoader().getParent());
    }
}
public class ClassExample {

    public void method() {
        System.out.println("method invoked....");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不务正业的攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值