【读码JDK】-java.lang.ClassLoader类Api介绍及测试

简介: jdk11与jdk8 之间类加载器的区别知道吗?

在这里插入图片描述
【读码JDK】java.lang包目录

几种类加载器

  1. Bootstrap ClassLoader

负责加载JDK自带的rt.jar包中的类文件,它是所有类加载器的父加载器,Bootstrap ClassLoader没有任何父类加载器。

  1. Extension ClassLoader(Platform ClassLoader)负责加载Java的扩展类库,也就是从jre/lib/ext目录下或者java.ext.dirs系统属性指定的目录下加载类。
  2. System ClassLoader(App ClassLoader)负责从classpath环境变量中加载类文件,classpath环境变量通常由"-classpath" 或 "-cp" 命令行选项来定义,或是由 jar中 Mainfest文件的classpath属性指定,System ClassLoader是Extension ClassLoader的子加载器
  3. 自定义加载器

java.lang.ClassLoader类Api介绍及测试

package lang;

import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.stream.Stream;

/**
 * @author jujun chen
 * @date 2020/03/23
 */
public class ClassLoaderTest {

    /**
     * 返回类加载器的名称,如果未指定返回null
     */
    @Test
    public void getName() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        //jdk9后,名字更名
        System.out.println(classLoader.getName()); //app
        System.out.println(classLoader.getParent().getName());//platform
    }


    /**
     * 加载指定全限定名的类,相当于调用 {@link ClassLoader#loadClass(String, boolean) loadClass(name,false)}
     * <p>
     * 不会输出 静态代码块中的内容
     *
     * @throws ClassNotFoundException
     */
    @Test
    public void loadClass() throws ClassNotFoundException {
        ClassLoader classLoader = this.getClass().getClassLoader();
        Class cls = classLoader.loadClass("lang.ChinesePeople");
    }


    /**
     * 返回父类加载器
     * <p>
     * 某些实现可能使用null来表示引导类加载器。 如果此类加载器的父级是引导类加载器,则此方法将在此类实现中返回null
     */
    @Test
    public void getParent() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        ClassLoader parentClassLoader = classLoader.getParent();
        System.out.println(parentClassLoader.getName());
        //返回null,BootStrapClassLoader并不是Java类
        ClassLoader parentClassLoader2 = parentClassLoader.getParent();
//        System.out.println(parentClassLoader2.getName());
    }


    /**
     * 返回此类加载器的未命名模块
     */
    @Test
    public void getUnnamedModule() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        Module module = classLoader.getUnnamedModule();
        System.out.println(module.getName());
    }


    /**
     * 返回系统类加载器。
     * <p>
     * 这是新ClassLoader实例的默认委托父级,通常是用于启动应用程序的类装入器
     */
    @Test
    public void getSystemClassLoader() {
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        //输出app
        System.out.println(systemClassLoader.getName());
    }

    /**
     * 返回平台类加载器
     */
    @Test
    public void getPlatformClassLoader() {
        ClassLoader platformClassLoader = ClassLoader.getPlatformClassLoader();
        System.out.println(platformClassLoader.getName());
    }

    /**
     * 该软件包给定的名字已被这个类加载器定义,如果未找到 返回null
     */
    @Test
    public void getDefinedPackage() {
        ClassLoader classLoader = getClass().getClassLoader();
        Package pk = classLoader.getDefinedPackage("lang");
        System.out.println(pk.getName());
    }

    /**
     * 返回此类加载器定义的所有软件包。返回的数组没有重复的软件包名
     */
    @Test
    public void getDefinedPackages() {
        ClassLoader classLoader = getClass().getClassLoader();
        Package[] packages = classLoader.getDefinedPackages();
    }

    /**
     * 设置此类加载器默认的断言状态
     *
     * <a>https://blog.csdn.net/dominic_z/article/details/104639171</a>
     * <a>http://blog.sina.com.cn/s/blog_ed7fd8610102v0f4.html</a>
     */
    @Test
    public void setDefaultAssertionStatus() {

    }


    /**
     * 设置命名包的包默认断言状态。 包默认断言状态确定将来初始化的类的断言状态,这些类属于命名包或其任何“子包”。
     * 名为p的包的子包是名称以“ p. ”开头的任何包。 例如, javax.swing.text是的一个子包javax.swing ,并且两个java.util和java.lang.reflect是子包java 。
     * <p>
     * 如果多个包默认值适用于给定的类,则与特定包最相关的包默认优先于其他包。 例如,如果javax.lang和javax.lang.reflect都具有与之关联的包默认值,则后一个包默认应用于javax.lang.reflect类。
     * <p>
     * 包默认值优先于类加载器的默认断言状态,并且可以通过调用setClassAssertionStatus(String, boolean)在每个类的基础上重写 。
     * <p>
     * 参数
     * packageName - 要设置其包默认断言状态的包的名称。 null值表示未命名的包为“当前”(请参阅The Java™ Language Specification的第7.4.2节)。
     * enabled - true如果此类加载器加载的类属于命名包或其任何子包,则默认情况下将启用断言, false如果它们默认情况下将禁用断言。
     */
    @Test
    public void setPackageAssertionStatus() {

    }


    /**
     * 为此类加载器中指定的顶级类及其中包含的任何嵌套类设置所需的断言状态。
     * 此设置优先于类加载器的默认断言状态,并优先于任何适用的每个包默认值。
     * 如果已经初始化了命名类,则此方法无效。 (初始化一个类后,其断言状态不会改变。)
     * 如果指定的类不是顶级类,则此调用将不会影响任何类的实际断言状态。
     * <p>
     * 参数
     * className - 要设置其断言状态的顶级类的完全限定类名。
     * enabled - true如果命名类要在初始化时(和如果)初始化时启用断言,则 false如果要禁用断言, false 。
     */
    @Test
    public void setClassAssertionStatus() {

    }


    /**
     * 将此类加载器的默认断言状态设置为false并丢弃与类加载器关联的任何包默认值或类断言状态设置。
     * <p>
     * 提供此方法是为了使类加载器可以忽略任何命令行或持久断言状态设置并“从一个干净的平板开始”
     */
    @Test
    public void clearAssertionStatus() throws ClassNotFoundException {
        ClassLoader classLoader = getClass().getClassLoader();
        classLoader.setDefaultAssertionStatus(true);
        Class cls = classLoader.loadClass("lang.ChinesePeople");
        //实例可以见ClassTest.desiredAssertionStatus Test
        System.out.println(cls.desiredAssertionStatus());
        //重置
        classLoader.clearAssertionStatus();
        System.out.println(cls.desiredAssertionStatus());
    }

    /**
     *查找具有给定名称的资源。资源是可以由类代码以独立于代码位置的方式访问的一些数据(图像、音频、文本等)。
     */
    @Test
    public void getResource() throws IOException {
        //测试Bean
        ChinesePeople chinesePeople = new ChinesePeople();
        System.out.println(chinesePeople.getClass().getResource(""));
        System.out.println(chinesePeople.getClass().getClassLoader().getResource(""));
        /**
         * file:/D:/javaprojects/java11-example/target/test-classes/lang/
         * file:/D:/javaprojects/java11-example/target/test-classes/
         */
        //资源类型为URL的enumeration
        Enumeration<URL> enumeration = chinesePeople.getClass().getClassLoader().getResources("");
        //返回流
        Stream<URL> stream = chinesePeople.getClass().getClassLoader().resources("ChinesePeople.class");
    }

    /**
     * 返回classLoader是否注册为具有并行能力
     *
     */
    @Test
    public void isRegisteredAsParallelCapable(){
        boolean b = this.getClass().getClassLoader().isRegisteredAsParallelCapable();
        System.out.println(b);
    }


    /**
     * 从用于加载类的搜索路径中查找指定名称的资源。此方法通过系统类加载器定位资源(请参阅getSystemClassLoader() )。
     */
    @Test
    public void getSystemResource() {
        URL url = this.getClass().getClassLoader().getSystemResource("");
        System.out.println(url);
        //还可以返回Enumeration<URL>

    }

    /**
     * 返回用于读取指定资源的输入流
     */
    @Test
    public void getResourceAsStream() {
        InputStream getResourceAsStream = this.getClass().getClassLoader().getResourceAsStream("");

        //getSystemResourceAsStream
    }


}

相关文章
|
6月前
|
Java API 数据处理
Java新特性:使用Stream API重构你的数据处理
Java新特性:使用Stream API重构你的数据处理
|
6月前
|
人工智能 数据可视化 测试技术
Postman 性能测试教程:快速上手 API 压测
本文介绍API上线后因高频调用导致服务器告警,通过Postman与Apifox进行压力测试排查性能瓶颈。对比两款工具在批量请求、断言验证、可视化报告等方面的优劣,探讨API性能优化策略及行业未来发展方向。
Postman 性能测试教程:快速上手 API 压测
|
6月前
|
Java 大数据 API
Java Stream API:现代集合处理与函数式编程
Java Stream API:现代集合处理与函数式编程
347 100
|
6月前
|
Java API 数据处理
Java Stream API:现代集合处理新方式
Java Stream API:现代集合处理新方式
356 101
|
6月前
|
并行计算 Java 大数据
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
362 101
|
6月前
|
安全 Java API
使用 Java 构建强大的 REST API 的四个基本技巧
本文结合探险领域案例,分享Java构建REST API的四大核心策略:统一资源命名、版本控制与自动化文档、安全防护及标准化异常处理,助力开发者打造易用、可维护、安全可靠的稳健API服务。
447 116
|
7月前
|
存储 Java API
Java Stream API:现代数据处理之道
Java Stream API:现代数据处理之道
425 188
|
6月前
|
人工智能 数据可视化 测试技术
AI 时代 API 自动化测试实战:Postman 断言的核心技巧与实战应用
AI 时代 API 自动化测试实战:Postman 断言的核心技巧与实战应用
806 11
|
6月前
|
存储 数据可视化 Java
Java Stream API 的强大功能
Java Stream API 是 Java 8 引入的重要特性,它改变了集合数据的处理方式。通过声明式语法,开发者可以更简洁地进行过滤、映射、聚合等操作。Stream API 支持惰性求值和并行处理,提升了代码效率和可读性,是现代 Java 开发不可或缺的工具。
134 0
Java Stream API 的强大功能
|
7月前
|
安全 Java API
Java日期时间API:从Date到Java.time
本文深入解析了Java 8中引入的全新日期时间API,涵盖LocalDate、LocalTime、LocalDateTime、ZonedDateTime等核心类的使用,以及时间调整、格式化、时区处理和与旧API的互操作。通过实例对比,展示了新API在可变性、线程安全与易用性方面的显著优势,并提供迁移方案与实战技巧,助你掌握现代Java时间处理的最佳实践。