当前位置: 首页 > news >正文

爱站seo工具惠州手机模板建站

爱站seo工具,惠州手机模板建站,优势网网站,做头像的网站有哪些Java类加载机制 类加载器类加载器的执行流程类加载器的种类加载器之间的关系ClassLoader 的主要方法Class.forName()与ClassLoader.loadClass()区别 双亲委派模型双亲委派 类加载流程优缺点 热部署简单示例 类加载器 类加载器的执行流程 类加载器的种类 AppClassLoader 应用类…

Java类加载机制

  • 类加载器
    • 类加载器的执行流程
    • 类加载器的种类
    • 加载器之间的关系
    • ClassLoader 的主要方法
    • Class.forName()与ClassLoader.loadClass()区别
  • 双亲委派模型
    • 双亲委派 类加载流程
    • 优缺点
  • 热部署简单示例

类加载器

类加载器的执行流程

在这里插入图片描述

类加载器的种类

AppClassLoader
应用类加载器,默认的系统类加载器,负责加载java应用种classpath中的类

设置 classpath java -cp D:\aaa Main.class 获取 classpath
System.getProperty(“java.class.path”)

ExtClasLoader
扩展类加载器,负责加载扩展目录中的java类。

设置扩展目录:java -Djava.ext.dirs=“D:\aa” Main.class
获取扩展目录:System.getProperty(“java.ext.dirs”)

从java9开始,扩展机制被移除,加载器被PlatFormClassLoader取代

BootStrapClassLoader
启动类加载器,负责加载JDK核心类库(/jre/lib)
由 C++/C 语言编写,无法通过java代码打印

用户自定义的ClassLoader
继承抽象类 ClassLoader 的自定义类加载器

加载器之间的关系

在这里插入图片描述
从JVM的角度来看,一共有两种类加载器,BootStrapClassLoaderjava 自定义的类加载器
其中 BootStrapClassLoader 是使用C/C++语言编写的 最高级别的 类加载器

Java 自定义的类加载器 都继承于抽象类 ClassLoader ,并且内部有一个parent 属性,指向父加载器(是组合,不是继承
ExtClassLoader 的 parent属性 是null,实际是通过native方法 关联 BootStrapClassLoader ,所以ExtClassLoader 的父类加载器 是 BootStrapClassLoader

JDK自带的类加载器有:BootStrapClassLoader,ExtClassLoader,AppClassLoader
三者并不是集成关系,而是组合

用户可以继承ClassLoader 来实现自己的类加载器,默认的父类加载器是 AppClassLoader

ClassLoader 的主要方法

//返回该类加载器的超类加载器
public final ClassLoader getParent()//加载名称为name的类,返回结果为java.lang.Class类的实例。如果找不到类,
//则返回 ClassNotFoundException异常。该方法中的逻辑就是双亲委派模式的实现
public Class<?> loadClass(String name) throws ClassNotFoundException//查找二进制名称为name的类,返回结果为java.lang.Class类的实例。
//这是一个受保护的方法,JVM鼓励我们重写此方法,需要自定义加载器遵循双亲委托机制,
//该方法会在检查完父类加载器之后被loadClass()方法调用。
protected Class<?> findClass(String name) throws ClassNotFoundException//根据给定的字节数组b转换为Class的实例,off和len参数表示实际Class信息在byte数组中的位置和长度,
//其中byte数组b是ClassLoader从外部获取的。
//这是受保护的方法,只有在自定义ClassLoader子类中可以使用。
protected final Class<?> defineClass(String name, byte[] b,int off,int len)//链接指定的一个Java类。使用该方法可以使用类的Class对象创建完成的同时也被解析。
//链接阶段主要是对字节码进行验证,
//为类变量分配内存并设置初始值同时将字节码文件中的符号引用转换为直接引用。
protected final void resolveClass(Class<?> c)//查找名称为name的已经被加载过的类,返回结果为java.lang.Class类的实例。这个方法是final方法,无法被修改。
protected final Class<?> findLoadedClass(String name)//它也是一个ClassLoader的实例,这个字段所表示的ClassLoader也称为这个ClassLoader的双亲。
//在类加载的过程中,ClassLoader可能会将某些请求交予自己的双亲处理。
private final ClassLoader parent;

Class.forName()与ClassLoader.loadClass()区别

public static Class<?> forName(String className)

  1. 是类方法
  2. 默认使用系统类加载器进行加载
  3. 加载一个指定的类,会对类进行初始化,执行类中的静态代码块,以及对静态变量的赋值等操作, 一般用于加载驱动,例如jdbc驱动

public Class<?> loadClass(String name)

  1. 是成员方法
  2. 懒加载,只是加载,不会解析更不会初始化所反射的类

双亲委派模型

rents Delegation Model
注意:双亲并不是指存在父母两个类加载器,实际只有一个parent 父加载器 并且是作为加载器的属性,而不是继承,可以理解为 雌雄同株

在这里插入图片描述

双亲委派 类加载流程

  1. 当一个类开始进行加载时,会先从判断这个类是否已经被加载了,如果已经加载了,返回已加载的类Class对象
  2. 如果还没有被加载,通过parent属性 将加载请求传递给上层类加载器进行加载
  3. 一直调用到扩展类加载器(ExtClassLoader),如果都没有找到已经被加载的Class对象,此时parent == null ,通过 findBootstrapClassOrNull() 方法传递给 BootStrapClassLoader 进行类加载
  4. 如果BootStrapClassLoader 没有加载成功,其下层类加载器开始尝试进行加载
  5. 如果一直到最底层的类加载器(用户自定义的类加载器)都没有加载成功,则抛出ClassNotFoundException异常

一句话概括:子类加载器调用父类加载器去加载类

源码如下:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loadedClass<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {if (parent != null) {// 如果有parent ,交给parent 类加载器进行加载c = parent.loadClass(name, false);} else {//没有parent,通过native方法委派给BootStrapClassLoader 进行加载c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {//如果父类没有加载出Class对象,开始尝试自己加载long t1 = System.nanoTime();//根据类的全限定名,获取Class 对象,分为两步//1.根据类的全限定名,获取字节码对象//2. 根据字节码的二进制流,调用defineClass()方法,生成Class对象c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}
}

优缺点

优点:

  1. 防止重复加载,确保一个类的全局唯一性

当一个类加载器要加载一个类,首先交给父类加载器进行加载,并且加载过程由syncronized锁控制。避免重复加载同一个类

  1. 确保JVM的安全,防止用户用自己编写的类替换核心类库中的类

例如:用户自定义一个java.lang.String的类,通过双亲委派模型,加载的还是核心类库中的String类,不会被用户自己定义的String类替换

缺点:
父类加载器不能访问子类加载器加载的类,有时需要打破双亲委派模型,例如Tomcat

热部署简单示例

public class MyClassLoader extends ClassLoader{/*** 文件路径*/final private String path;protected MyClassLoader(String path) {this.path = path;}/*** 重写findClass,实现自己的类加载器* 1. 获取class文件的字节流* 2. 调用defineClass 将字节流 转化为 CLass 对象* @param name* @return* @throws ClassNotFoundException*/@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {// 读取字节码的二进制流byte[] b = loadClassFromFile(name);// 调用 defineClass() 方法创建 Class 对象Class<?> c = defineClass(name, b, 0, b.length);return c;} catch (IOException e) {throw new ClassNotFoundException(name);}}/*** 如果要遵循双亲委派模型,则不用重写loadClass方法* @param name* @return* @throws ClassNotFoundException*/@Overridepublic Class<?> loadClass(String name) throws ClassNotFoundException {//为了测试方便,这里简单打破下双亲委派模型,先从自定义类加载器进行加载//如果不想打破双亲委派模型,path路径可以设置非classpath下的路径,手动复制class文件到对应目录下synchronized (getClassLoadingLock(name)) {Class<?> c = findLoadedClass(name);if (c == null) {//先从自定义类加载器进行加载,这里打破了双亲委派模型try {c = findClass(name);} catch (ClassNotFoundException ignored) {}//自定义类加载器加载失败,交给父 类加载器if(c == null){return super.loadClass(name);}}return c;}}private byte[] loadClassFromFile(String name) throws IOException {String fileName = name.replace('.', File.separatorChar) + ".class";String filePath = this.path + File.separatorChar + fileName;try (InputStream inputStream = new FileInputStream(filePath);ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {int nextValue;while ((nextValue = inputStream.read()) != -1) {byteStream.write(nextValue);}return byteStream.toByteArray();}}
}
public class ApplicationConfig {public void getConfig(){System.out.println("这是我的配置...");}}
public class HotDeploymentTest {public static void main(String[] args) throws Exception{Scanner sc = new Scanner(System.in);while(true){MyClassLoader loader = new MyClassLoader("E:\\Work\\classloader\\target\\classes");Class<?> aClass = loader.loadClass("cn.rwto.sample.ApplicationConfig");Object applicationConfig = aClass.newInstance();Method method = aClass.getMethod("getConfig");method.invoke(applicationConfig);Thread.sleep(5000);}}
}

在这里插入图片描述
在这里插入图片描述
在不关闭进程的情况下,修改代码,重新编译,控制台发现 打印的内容跟着改变,热部署实现完毕!

http://www.yayakq.cn/news/540963/

相关文章:

  • 网站子站建设合同样本电子简历表格手机版
  • 宁波专业网站推广平台便宜装饰设计是什么
  • 医院网站建设投标要求wordpress 1 s
  • 青海城乡住房建设厅网站做母婴网站
  • 做网站会很忙吗外贸公司用的采购储运财务软件
  • 网站建设与排名什么网站做啤酒
  • 做网站界面用的软件卖备案域名被抓
  • 外贸移动商城网站开发网站的管理跟新维护有哪些
  • 网站色差表亚洲电视全球运营中心
  • 使用模板建站wordpress 文章输出
  • 企业网站建站流程app制作公司排行榜
  • 菜鸟移动端网站开发福田服务商app软件安装
  • soho需要建网站吗wordpress搜索主题
  • 招工网站服务做网站的客户多吗
  • 网站定制制作公司惠州网站建设怎么样
  • 网站空间商是什么哪里网页建设便宜
  • 国内自适应网站案例网站开发会遇到的问题
  • 网站建设尾款结算申请seo排名培训学校
  • 海拉尔做网站的公司wordpress网页没法评论
  • 哪类网站赚钱 优帮云wordpress 获取指定分类
  • 高端营销网站建设网站模板及源码
  • 更改host文件把淘宝指向自己做的钓鱼网站国际大新闻最新消息
  • 惠民建设局网站是哪个百度云如何做网站
  • 网站布局的三种基本方法广州网络推广选择
  • 做网站用什么电脑网站开发 路由
  • 天津网站建设推荐安徽秒搜科技网页设计html代码大全
  • 网站优化及推广方案网上申请开办公司流程
  • 怎样建设网站是什么湖北网站建设论文题目要求
  • 成都免费招聘网站微信网页版无法登录
  • php网站开发费用营销管理