java 编程基础 类加载器
什么是类加载器
细说类加载机制
三种类加载器:
- Bootstrap ClassLoader: 根类加载器, 平台加载器的父加载器
- Platform ClassLoader: 平台类加载器,系统加载器的父加载器。在Java8和之前,这个加载器应该叫做扩展加载器(ExtClassLoader)
- System ClassLoader: 系统类加载器。
1,根类加载器:
2,平台类加载器:
3,系统加载器:
package com.vgxit.classloeader;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
public class ClassLoaderPropTest {
public static void main(String[] args) throws IOException {
//首先获取对应的系统加载器
ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
System.out.println("系统加载器:" + systemLoader);
//打印系统加载器的路径
Enumeration<URL> enumeration = systemLoader.getResources("");
while (enumeration.hasMoreElements()) {
System.out.println(URLDecoder.decode(enumeration.nextElement().toString(), "utf-8"));
}
//获取系统加载器的父加载器(平台类加载器)
ClassLoader platformLoader = systemLoader.getParent();
System.out.println("平台类加载器" + platformLoader);
//打印一下平台类加载器的路径
Enumeration<URL> enumeration1 = platformLoader.getResources("");
while (enumeration1.hasMoreElements()) {
System.out.println(URLDecoder.decode(enumeration1.nextElement().toString(), "utf-8"));
}
//获取根加载器
ClassLoader bootstrapLoader = platformLoader.getParent();
System.out.println("根加载器是:" + bootstrapLoader);
}
}

三种类加载机制:
- 全盘负责:所谓全盘负责,就是当一个类加载器负责加载某C1ass时,该class所依赖的和引用的其他class也将由该类加载器负责载入,除非显式使用另外一个类加载器来载入
- 父类委托:所谓父类委托,是先让parent(父)类加载器试图加载该class,只有在父类加载器无法加载该类时才尝试从自己的类路径中加载该类。
- 缓存机制:缓存机制将会保证所有加载过的C1ass都会被缓存,当程序中需要使用某个class时,类加载器先从缓存区中搜寻该C1ass,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将其转换成C1ass对象,存入缓存区中。这就是为什么修改了代码后,必须重新启动JVM程序所做的修改才会生效的原因。
类加载器工作步骤
自定义类加载器
- (1), loadClass(String name, boolean resove) 该方法是ClassLoader的入口点,根据指定名称来加载。系统就是调用ClassLoader的该方法来获取指定类Class对象。
- (2), findClass(String name): 根据指定名称来加载类。
- 用findLoadedClass(String name)来检查是否己经加载类,如果已经加载则直接返回。
- 在父类加载器上调用loadClass方法。 果父类加载器为null,则使用根类加载器来加载
- 调用findClass(String)方法查找类
package com.zmd.myclassloader; import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; /**
* @ClassName MyClassLoader
* @projectName: object1
* @author: Zhangmingda
* @description: 自定义加载器,继承ClassLoader类
* date: 2021/5/15.
*/
public class MyClassLoader extends ClassLoader{
/**
* @param name 重写findClass 方法 name为类名称
* @return 返回加载好的类
* @throws ClassNotFoundException 异常
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//定义好要返回的类
Class<?> cls = null;
//替换类名路径.为目录/
String filePath = name.replace('.','/');
String javaFileName = filePath + ".java";
String classFileName = filePath + ".class";
File javaFile = new File(javaFileName);
File classFile = new File(classFileName);
System.out.println(javaFileName);
if (!javaFile.exists() && !classFile.exists()){
throw new ClassNotFoundException("类:" + name + "不存在");
}else if (javaFile.exists()){
if (! classFile.exists() || classFile.lastModified() < javaFile.lastModified()){
try {
if (! complie(javaFile) || ! classFile.exists()){
throw new ClassNotFoundException("类:" + name + "编译失败");
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
//编译成功,读取二进制文件,加载到内存中,转化成对应的Class对象
try (FileInputStream fileInputStream = new FileInputStream(classFile)) {
//定义存储二进制数据的byte数组
byte[] classBytes = new byte[ (int) classFile.length()];
int readLen = fileInputStream.read(classBytes);
//转化成Class对象
cls = defineClass(name,classBytes,0, readLen);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return cls;
}
/**
* 编译动作
*/
private boolean complie(File javaFile) throws IOException, InterruptedException {
System.out.println("开始编译:" + javaFile.getPath());
//操作系统执行编译动作
try {
Process process = Runtime.getRuntime().exec("javac " + javaFile);
process.waitFor();
int result = process.exitValue();
System.out.println("result:" + result);
return result == 0;
}catch (InterruptedException e) {e .printStackTrace();}
//等待当前进程完成
return false;
}
/**
* 入口main方法测试
*/
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
if (args.length < 1){
System.err.println("没有指定目标类");
System.err.println(" java com.zmd.myclassloader.MyClassLoader com.zmd.myclassloader.Test hh haa");
return;
}
String className = args[0];
String[] runArgs = new String[args.length -1];
System.out.println("className:"+ className);
System.arraycopy(args,1, runArgs,0, runArgs.length);
//构建加载器,加载类
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> cls = myClassLoader.loadClass(className);
//通过反射执行
Method method = cls.getMethod("main",runArgs.getClass());
method.invoke(null,new Object[]{runArgs});
}
}Test 类
package com.zmd.myclassloader; /**
* @ClassName Test
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/5/15.
*/
public class Test {
public static void main(String[] args) {
System.out.println("This is Test class ,args :" + args.toString() );
}
}
java 编程基础 类加载器的更多相关文章
- Java中的类加载器--Class loader
学习一下Java中的类加载器,这个是比较底层的东西,好好学习.理解一下. 一.类加载器的介绍 1.类加载器:就是加载类的工具,在java程序中用到一个类,java虚拟机首先要把这个类的字节码加载到内 ...
- 黑马程序员——【Java高新技术】——类加载器
---------- android培训.java培训.期待与您交流! ---------- 一.概述 (一)类加载器(class loader) 用来动态加载Java类的工具,它本身也是Java类. ...
- Java中的类加载器
转载:http://blog.csdn.net/zhangjg_blog/article/details/16102131 从java的动态性到类加载机制 我们知道,Java是一种动态语言.那么怎 ...
- Java中的类加载器以及Tomcat的类加载机制
在加载阶段,虚拟机需要完成以下三件事情: 1.通过一个类的全限定名来获取其定义的二进制字节流. 2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构. 3.在Java堆中生成一个代表这个类 ...
- Java入门——(1)Java编程基础
Java入门--(1)Java编程基础 第二章 Java编程基础 JAVA 代码的基本格式: 修饰符 class 类名{ 程序代码 } 2.1关键字:赋予了特殊含义的单词. 2.2标识符: ...
- Java开发知识之Java编程基础
Java开发知识之Java编程基础 一丶Java的基础语法 每个语言都有自己的语法规范.例如C++ 入口点是main. 我们按照特定格式编写即可. Java也不例外. Java程序的语法规范就是 Ja ...
- java编程基础二进制
0.java编程基础 01.二进制(原码,反码,补码) 02.位运算 03.移位运算符 二进制 原码,反码,补码 1.基本概念 二进制是逢2进位的进位制,0,1是基本算符. 现在的电子计算机技术全部使 ...
- Java编程基础-面向对象(中)
本章承接Java编程基础-面向对象(上)一文. 一.static关键字 在java中,定义了一个static关键字,它用于修饰类的成员,如成员变量.成员方法以及代码块等,被static修饰的成员具备一 ...
- Java编程基础——数组和二维数组
Java编程基础——数组和二维数组 摘要:本文主要对数组和二维数组进行简要介绍. 数组 定义 数组可以理解成保存一组数的容器,而变量可以理解为保存一个数的容器. 数组是一种引用类型,用于保存一组相同类 ...
随机推荐
- Perl语言编程(大骆驼)
啰嗦几句 Perl的时代已经过去,现在年轻的同事们基本上都在用Python了.但个人认为单就生物信息文本处理而言,Perl语言是绝对够用的.最主要的是,前辈们搭建的流程大多数是Perl写的,因此,如果 ...
- Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议
Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议 索引 索引是一种存储引擎快速查询记录的一种数据结构. 注意 MYSQL一次查询只能使用一个索引 ...
- 【MetDNA】基于代谢反应网络的大规模代谢物结构鉴定新算法
代谢是生命体内化学反应的总称,其所包含的代谢物变化规律可直接反映生命体的健康状态.非靶向代谢组学(untargeted metabolomics)可以在系统水平测量生命体内生理或病理状态下所有代谢物的 ...
- mac 下 如何在同一窗口打开多个终端并实现快捷键切换
相信大家编代码的时候都会遇到,每次需要在头文件,库文件和源码文件中编代码的时候,总是需要在几个文件中切换来切换去的,而且一个文件就一个终端窗口,每次都要用鼠标点来点去,非常麻烦,所以如果能把这几个文件 ...
- Linux-普通用户和root用户任意切换
普通用户切换为root: 1.[xnlay@bogon ~]$含义:xnlay代表当前用户,bogon指的是主机名,~表示当前用户,$表示普通用户:[root@bogon ~]#root代表是超级用户 ...
- 利用抖音Cookie充值接口提取支付链接,个人调起原生微信h5支付宝h5支付
最近开始搞一些个人支付通道的开发,方便个人不用和第三方平台签约就能收款,省去很多流程手续的成本. 然后翻了一下网上并没有太多现成的技术教程,只能自己研究着搞了. 这次要分享的是利用抖音的充值接口,去分 ...
- tensorboard No dashboards are active for the current data set.
修改一下启动命令时的路径 位置示例: 命令为 E:\PYTHON_PROJECT\testTF\inceptionV1_net\log>tensorboard --logdir=TEC4FN ...
- 学习Java的第十八天
一.今日收获 1.java完全学习手册第三章算法的3.1比较值 2.看哔哩哔哩上的教学视频 二.今日问题 1.在第一个最大值程序运行时经常报错. 2.哔哩哔哩教学视频的一些术语不太理解,还需要了解 三 ...
- 一次“不负责任”的 K8s 网络故障排查经验分享
作者 | 骆冰利 来源 | Erda 公众号 某天晚上,客户碰到了这样的问题:K8s 集群一直扩容失败,所有节点都无法正常加入集群.在经过多番折腾无解后,客户将问题反馈到我们这里,希望得到技术支持 ...
- iOS 的文件操作
直接上操作 效果:将一张图片写入文件 (图片本身已经在Assets.xcassets里面了) 1.获取当前app的沙盒路径 NSString *documentPath = NSSearchPathF ...