JVM Class加载过程详解

类加载过程

JVM会通过加载、连接、初始化3个步骤来对该类进行初始化
在这里插入图片描述

类加载器

类加载器可以分为4种:启动类加载器,拓展类加载器,应用类加载器,自定义类加载器
在这里插入图片描述

做个简单demo测试:

System.out.println(String.class.getClassLoader());
System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());//ext包下面的类
System.out.println(ClassLoaderTest1.class.getClassLoader());//本地测试类
null
sun.misc.Launcher$ExtClassLoader@60e53b93
sun.misc.Launcher$AppClassLoader@18b4aac2

第一个结果输出为什么是null?

  • Bootstrap ClassLoader由C++实现,Java中找不到对应的类

JVM加载采用双亲委派机制,主要出于安全考虑。Loading的过程可以理解为:
findInCache --> parent.loadClass --> findClass
在这里插入图片描述
注:父加载器不是"类加载器的加载器",也不是"类加载器的父类加载器"!!!

System.out.println(ClassLoaderTest2.class.getClassLoader());   
System.out.println(ClassLoaderTest2.class.getClassLoader().getClass().getClassLoader());      
System.out.println(ClassLoaderTest2.class.getClassLoader().getParent().getClass().getClassLoader()); 
System.out.println(ClassLoaderTest2.class.getClassLoader().getParent());
sun.misc.Launcher$AppClassLoader@18b4aac2
null
null
sun.misc.Launcher$ExtClassLoader@6e0be858

自定义类加载器
为什么要用自定义类加载器?

  • 我们需要的类不一定存放在已经设置好的ClassPath下,对于自定义路径中的class类文件的加载,我们需要自己的ClassLoader
  • 有时我们可能是从网络的输入流中读取类,这就需要做一些加密和解密操作,这就需要自己实现加载类的逻辑,当然其他的特殊处理也同样适用
  • 可以定义类的实现机制,实现类的热部署

怎样写一个自定义类加载器?源码比较简单,这里不再罗列

  • 继承ClassLoader
  • 重写findClass方法
  • findClass方法调用defineClass方法(将byte[]类型的数据转换成Class)

具体实现如下:

public class HelloJVM {
    public void hello() {
        System.out.println("Hello JVM!");
    }
}
public class CustomClassLoader extends ClassLoader {
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] data = loadClassData();
        return super.defineClass(name, data, 0, data.length);
    }

    private byte[] loadClassData() {
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        byte[] data = null;
        try {
            is = new FileInputStream(new File("/****/HelloJVM.class"));
            baos = new ByteArrayOutputStream();
            int b = 0;
            byte[] buffer = new byte[1024];
            while ((b = is.read(buffer)) != -1) {
                baos.write(buffer, 0, b);
            }
            data = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
                baos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return data;
    }

    public static void main(String[] args) throws Exception {
        CustomClassLoader classLoader = new CustomClassLoader();
        Class<?> clazz = classLoader.loadClass("HelloJVM");
        Object obj = clazz.newInstance();
        clazz.getMethod("hello").invoke(obj);
        System.out.println(clazz.getClassLoader());
    }
}

执行结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值