初识 Java 类加载器

简介: 什么是ClassLoaderClassLoader简称类加载器,主要用于加载和校验编译后的Java文件(即:以.class结尾的文件);有哪些类加载器(ClassLoader)AppClassLoader(应用类加载器)ExtClassLoader(扩展类加载器注意:JDK1.8后被修改为平台类加载器)BootstrapClassLoader(启动类加载器)

什么是ClassLoader


ClassLoader简称类加载器,主要用于加载和校验编译后的Java文件(即:以.class结尾的文件);


有哪些类加载器(ClassLoader)


AppClassLoader(应用类加载器)


ExtClassLoader(扩展类加载器注意:JDK1.8后被修改为平台类加载器)


BootstrapClassLoader(启动类加载器)


获取类加载器


通过简单的demo来得到类加载器

public class User {
    public static void main(String[] args) {
        User user = new User();
        Class<? extends User> userClass = user.getClass();
        System.out.println(userClass.getClassLoader());
        System.out.println(userClass.getClassLoader().getParent());
        System.out.println(userClass.getClassLoader().getParent().getParent());
    }
}


结果显示:


sun.misc.Launcher$AppClassLoader@73d16e93


sun.misc.Launcher$ExtClassLoader@15db9742


null 这里涉及到底层所以返回null


类加载器的加载顺序


由于当前的类加载器使用双亲模式


首先加载系统类加载器,此时系统类加载器会判断当前类是否已近是当前系统已定的类,如果是加载系统类,不会初始化被加载的类,不存在则由ExtClassLoader加载


ExtClassLoader检测加载,一般都是lib包中,不存在则交给AppClassLoader加载


AppClassLoader检测加载类,当前应用加载器会从当前应用中(就是启动类或者整个程序

中)查找需要加载的类,存在即加载程序的类,不存在交给用户定义的类加载器处理


使用双亲模式的好处,可以保护Java程序的安全,防止非法的加载Class


用户可以使用自定义类加载器用来实现对不同位置的类的加载和调用

mkdir -p aa/bb
vim aa/bb/Hello.java
javac aa/bb/Hello.java


Hello.java 代码

package aa.bb;
public class Hello {
    static {
        System.out.println("init ...");
    }
}


自定义类加载器

mkdir -p aa/classloader
vim aa/classloader/MyClassLoader.java
javac -Xlint:deprecation aa/classloader/MyClassLoader.java


MyClassLoader.java 代码

package aa.classloader;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class MyClassLoader extends ClassLoader {
    private String path;
    public MyClassLoader(String path) {
        this.path = path;
    }
    @Override
    public Class<?> findClass(final String name) throws ClassNotFoundException {
        final String classPath = path + "/" + name.replace(".","/") + ".class";
        try (InputStream in = new FileInputStream(classPath);
        ByteArrayOutputStream out = new ByteArrayOutputStream();) {         
            int len;
            byte[] bytes = new byte[4096];
            while ((len = in.read(bytes)) != -1) {
                out.write(bytes, 0, len);
            }
            byte[] byteArray = out.toByteArray();
            return defineClass(name, byteArray, 0, byteArray.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}


创建测试类  HelloTest.java

mkdir -p aa/test
vim aa/test/HelloTest.java
javac aa/test/HelloTest.java


package aa.test;
import aa.classloader.MyClassLoader;
public class HelloTest {
    public static void main(String[] args) throws Exception {
        String path = HelloTest.class.getClassLoader().getResource("./").getPath();
        MyClassLoader myClassLoader = new MyClassLoader(path);
        Class<?> clazz = myClassLoader.findClass("aa.bb.Hello");
        clazz.newInstance();
    } 
}


运行结果

java aa.test.HelloTest
init ...


总结:


1.使用自定义的类加载器的时候需要继承ClassLoader来实现class的加载


2.在加载的过程中须要使用 ByteArrayOutputStream 内存流


3.解析的时候需要使用父类来解析获得二进制信息以此得到Class的信息(必须调用 super.defineClass(fileName, classBytes, 0, classBytes.length);)


4.使用自定义的类加载器可以没有限制的在其他的地方加载类


参考



Java中自定义ClassLoader和ClassLoader的使用非


https://blog.csdn.net/weixin_45492007/article/details/98875060



目录
相关文章
|
2天前
|
Java 编译器
<Java> 类和对象专题大汇总.(学不会包退)
<Java> 类和对象专题大汇总
12 0
|
3天前
|
安全 Java 索引
Java字符串类详解
Java字符串类详解
11 1
|
17小时前
|
存储 Java
Java类的定义与实践
Java类的定义与实践
|
19小时前
|
Java 关系型数据库
Java类的设计与封装深入解析
Java类的设计与封装深入解析
|
1天前
|
安全 Java API
滚雪球学Java(44):掌握Java编程的关键:深入解析System类
【5月更文挑战第19天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
8 0
滚雪球学Java(44):掌握Java编程的关键:深入解析System类
|
1天前
|
编解码 安全 算法
Java多线程基础-18:线程安全的集合类与ConcurrentHashMap
如果这些单线程中的集合类确实需要在多线程中使用,该怎么办呢?思路有两个: 最直接的方式:使用锁,手动保证。如多个线程修改ArrayList对象,此时就可能有问题,就可以给修改操作进行加锁。但手动加锁的方式并不是很方便,因此标准库还提供了一些线程安全的集合类。
16 4
|
1天前
|
安全 Java 容器
Java 多线程系列Ⅶ(线程安全集合类)
Java 多线程系列Ⅶ(线程安全集合类)
|
1天前
|
Java 程序员
Java中的多线程编程:理解并应用Thread类和Runnable接口
【5月更文挑战第28天】在Java中,多线程编程是一个重要的概念,它允许同时执行多个任务。本文将深入探讨Java的多线程编程,包括Thread类和Runnable接口的使用,以及如何在实际项目中应用这些知识。我们将通过实例来理解这些概念,并讨论多线程编程的优点和可能的挑战。
|
1天前
|
存储 Java 程序员
滚雪球学Java(43):探究 Java 中的 Class 类:透视类的本质和实现原理
【5月更文挑战第18天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
4 0
滚雪球学Java(43):探究 Java 中的 Class 类:透视类的本质和实现原理
|
2天前
|
存储 Java 编译器
『Java』类和对象
『Java』类和对象