类加载器

 

什么是类加载器?

类加载器:类加载器是负责加载类的对象。将class文件(硬盘)加载到内存生成Class对象。所有的类加载器都是 java.lang.ClassLoader 的子类。

解释上图:当我们要用一个类,这个类叫做Hello类,这个类假设不在内存中,我们现在需要用到它了,此时虚拟机就会在内存中说:内存中有没有Hello啊?内存说没有。虚拟机又说:类加载器加载一下这个Hello类,而实际中类加载器有很多;虚拟机会首先叫AppClassLoader(应用类加载器)加载一下Hello类,但是AppClassLoader在加载这个Hello类之前会去找它的父加载器ExtClassLoader(扩展类加载器)去问一下:你加载了这个Hello类吗?此时ExtClassLoader说等下,我去问一下父类BootstrapClassLoader(引导类加载器)有没有加载这个Hello类?ExtClassLoader说我没有加载这个Hello类,那么ExtClassLoader得到消息后就回复AppClassLoader类说我没有加载这个类。此时AppClassLoader类会自己去加载这个Hello类,我们就可以使用这个Hello类了。如果BootstrapClassLoader说我已经加载了Hello类了,那么就会对ExtClassLoader说:我已经加载了,拿去用,ExtClassLoader对AppClassLoader说我加载了,拿去用吧,AppClassLoader直接使用。

综上可得知:一个类在我们的虚拟机中,只允许被加载一次。

我们可以使用:类.class.getClassLoader()获得加载自己的类加载器。

那么我们现在就遇到一个问题:第一个类是从哪里来的?答:在JVM中有那么一个程序它不是java编写的,它是由c、c++编写的。我们称之为引导类加载器,这个是给它的名称而不是具体的类,所以它不是类,它是一个null,是一个空对象。

类加载器加载机制:全盘负责委托机制。

全盘负责:A类如果要使用B类(B类不在内存中),负责加载A类的加载器就需要负责把B类加载进来。谁用谁加载。

 

委托机制:A类加载器如果要加载资源B,必须询问父类加载是否加载。

                   如果加载,将直接使用。

                   如果没有机制,自己再加载。

采用 全盘负责委托机制 保证 一个class文件 只会被加载一次,形成一个Class对象

   注意:

         如果一个class文件,被两个类加载器加载,将是两个对象。(理解成JDK加载了一次,另一个程序也加载了一次)

          第一个加载器是A:h.getClass() -->A                第二个加载器是B: h.getClass()  -->B

          很有可能出现有提示 com.umanwu.Hello  不能强制成 com.umanwu.Hello

          会出现在自定义类加载出现可以将一个class文件加载多次。

 

 

 

类加载的演示:

  查看引导类加载器的内容:

 

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo {

	@Test
	public void demo01() {
		// 查看引导类加载器加载的内容
		// * JDK固定配置信息,sun.boot.class.path 用于表示 引导类加载器所加载的内容
		String paths = System.getProperty("sun.boot.class.path");
		String[] allPath = paths.split(";");
		for (String p : allPath) {
			System.out.println(p);
		}
	}
}


输出的结果是:

 

 

  查看引导类加载器加载的类型:

 

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo {

	@Test
	public void demo02(){
		// 查看引导类加载器加载的类型
		ClassLoader cl = String.class.getClassLoader();
		System.out.println(cl);
	}
}

输出的结果是:null

 

 

   查看扩展类加载器的内容:

 

package com.umanwu.classloader;

import org.junit.Test;

import sun.net.spi.nameservice.dns.DNSNameService;

public class ClassLoaderDemo_02 {
	
	@Test
	public void demo01(){
		// 查看扩展类加载器加载的内容
		// * JDK固定配置信息,java.ext.dirs 用于表示 扩展类加载器所加载的内容
		String paths = System.getProperty("java.ext.dirs");
		String[] allPath = paths.split(";");
		for(String p : allPath){
			System.out.println(p);
		}
	}
}

输出:

 

   查看扩展类加载器的类型:

 

package com.umanwu.classloader;

import org.junit.Test;

import sun.net.spi.nameservice.dns.DNSNameService;

public class ClassLoaderDemo_02 {
	
	@Test
	public void demo02(){
		// 查看扩展类加载器的类型:Launcher$ExtClassLoader($表示匿名内部类)
		ClassLoader cl = DNSNameService.class.getClassLoader();//JDK中随便找一个类的,需要添加允许访问规则
		System.out.println(cl);
	}

}

添加允许访问规则:

 

输出:sun.misc.Launcher$ExtClassLoader@2503dbd3
 

 

   查看应用类加载器的内容:

 

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo_03 {
	
	@Test
	public void demo01(){
		// 查看应用类加载器加载的内容: 项目/bin (编译后内容) ,自己编写类由应用类加载加载
		String paths = System.getProperty("java.class.path");
		String[] allPath = paths.split(";");
		for(String p : allPath){
			System.out.println(p);
		}
	}
}
自己编写类由应用类加载加载
		String paths = System.getProperty("java.class.path");
		String[] allPath = paths.split(";");
		for(String p : allPath){
			System.out.println(p);
		}
	}
}

 

输出:

 

   查看应用类加载器加载的类型:

 

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo_03 {
	
	@Test
	public void demo02(){
		ClassLoader cl = ClassLoaderDemo_03.class.getClassLoader();
		System.out.println(cl);
	}

}

输出:sun.misc.Launcher$AppClassLoader@6d06d69c
 

 

三个加载器之间的关系:

 

package com.umanwu.classloader;

import org.junit.Test;

public class ClassLoaderDemo_04 {
	
	
	@Test
	public void demo01(){
		//3个类加载的关系
		
		ClassLoader c1 = ClassLoaderDemo_04.class.getClassLoader();
		System.out.println(c1);	//应用 (AppClassLoader)
		
		ClassLoader c2 = c1.getParent();
		System.out.println(c2);	//扩展(ExtClassLoader)
		
		ClassLoader c3 = c2.getParent();
		System.out.println(c3);	//引导(null)
	}

}

输出:

 

sun.misc.Launcher$AppClassLoader@6d06d69c
sun.misc.Launcher$ExtClassLoader@2503dbd3
null
 

 

 

扩展:

 

//获得所有属性配置
Properties properties = System.getProperties();
for (String string : properties.stringPropertyNames()) {
	System.out.println(string);
}

//引导:sun.boot.class.path 用于表示引导类加载器所加载的内容
//扩展:java.ext.dirs 用于表示扩展类加载器所加载的内容
//应用:java.class.path 用于表示应用加载器所加载的内容

 

 

 

 

 

【SCI一区复现】基于配电网韧性提升的应急移动电源预配置和动态调度(下)—MPS动态调度(Matlab代码实现)内容概要:本文档围绕“基于配电网韧性提升的应急移动电源预配置和动态调度”主题,重点介绍MPS(Mobile Power Sources)动态调度的Matlab代码实现,是SCI一区论文复现的技术资料。内容涵盖在灾害或故障等极端场景下,如何通过优化算法对应急移动电源进行科学调度,以提升配电网在突发事件中的恢复能力与供电可靠性。文档强调采用先进的智能优化算法进行建模求解,并结合IEEE标准测试系统(如IEEE33节点)进行仿真验证,具有较强的学术前沿性和工程应用价值。; 适合人群:具备电力系统基础知识和Matlab编程能力,从事电力系统优化、配电网韧性、应急电源调度等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①用于复现高水平期刊(SCI一区、IEEE顶刊)中关于配电网韧性与移动电源调度的研究成果;②支撑科研项目中的模型构建与算法开发,提升配电网在故障后的快速恢复能力;③为电力系统应急调度策略提供仿真工具与技术参考。; 阅读建议:建议结合前篇“MPS预配置”内容系统学习,重点关注动态调度模型的数学建模、目标函数设计与Matlab代码实现细节,建议配合YALMIP等优化工具包进行仿真实验,并参考文中提供的网盘资源获取完整代码与数据。
一款AI短视频生成工具,只需输入一句产品卖点或内容主题,软件便能自动生成脚本、配音、字幕和特效,并在30秒内渲染出成片。 支持批量自动剪辑,能够实现无人值守的循环生产。 一键生成产品营销与泛内容短视频,AI批量自动剪辑,高颜值跨平台桌面端工具。 AI视频生成工具是一个桌面端应用,旨在通过AI技术简化短视频的制作流程。用户可以通过简单的提示词文本+视频分镜素材,快速且自动的剪辑出高质量的产品营销和泛内容短视频。该项目集成了AI驱动的文案生成、语音合成、视频剪辑、字幕特效等功能,旨在为用户提供开箱即用的短视频制作体验。 核心功能 AI驱动:集成了最新的AI技术,提升视频制作效率和质量 文案生成:基于提示词生成高质量的短视频文案 自动剪辑:支持多种视频格式,自动化批量处理视频剪辑任务 语音合成:将生成的文案转换为自然流畅的语音 字幕特效:自动添加字幕和特效,提升视频质量 批量处理:支持批量任务,按预设自动持续合成视频 多语言支持:支持中文、英文等多种语言,满足不同用户需求 开箱即用:无需复杂配置,用户可以快速上手 持续更新:定期发布新版本,修复bug并添加新功能 安全可靠:完全本地本地化运行,确保用户数据安全 用户友好:简洁直观的用户界面,易于操作 多平台支持:支持Windows、macOS和Linux等多个操作系统
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值