引用

classloader机制

  • 如下图所示,java的classloader是双亲委派机制。会首先从父classloader加载指定的class,如果加载不到才会从子classloader中加载。
  • 主要这里的图片主要用于体现classloader的父子关系,实际上实现时并不一定存在继承关系。比如AppClassLoader的父classLoader是ExtClassLoader,但是实际实现时两者都是继承自URLClassLoader的。

自定义classloader

Animal类&包结构

  • 包结构如图:

测试入口

  • 输出结果如图所示:

思考1

  • 我们定义的classloader真的被运行了吗?
  • 实际上如果打一些日志或者是debug进去看下,会发现我们重写的方法并没有被执行,这是java classloader的委派机制搞的鬼,我们可以发现定制的TinglangClassLoader的父classloader为URLClassLoader,在URLClassLoader中就已经找到了Animal类了。
  • 所以这里可以重写loadClass方法来保证我们的classLoader被执行。

思考2

  • 我们将代码做一些变种,如下图所示:
  • 执行结果直接抛异常了
  • 这是由于Animal类来源于两个不同的类加载器。如果只是需要执行Animal中的say方法的话,直接反射调用即可,如下图所示:

思考3

  • 我们再将代码做一下变化,如下图所示,Animal作为一个普通内部类来实现,如下图所示:
  • 可以看到代码已经提示无法实例化内部类了,这个是由于要实例化非静态的内部类对象,必须要先实例化外部类的对象,可以采用下面的方法来解决:
  • ps:这里内部类有public修饰符~

思考4

  • tomcat也是定义了自己的classloader,那么为啥不用jvm提供的classloader呢?
  • 结合相关的资料主要是三个方面的目的:
    • webapp隔离:由于各个webapp中的class和lib文件需要相互隔离,不能出现一个应用中加载的类库会影响到另一个应用的情况。
    • 安全性:与jvm相同,tomcat也期望使用单独的classloader去装载tomcat自身的类库,以免其他恶意或者无意的破坏。
    • 热部署:tomcat修改文件可以不用重启自动装载类库,这个点后面我们会单独抽取示例。

思考5

  • 既然ExtClassLoader是读取特定目录下的class文件,那么如果我将自定义的class文件移到$JAVA_HOME/jre/lib/ext/目录下是不是就能够达到指定classloader加载类的目标呢?
  • 这个点是可以的,但是必须要求是jar。

思考6

  • 类加载器常见的用途有类的隔离和热替换,类的隔离非常好理解,那么热替换呢?
  • 仍然以我们之前的代码为例,如下图所示:
  • 在程序运行过程中更新并编译Animal类中say方法
  • 可以看到运行结果如图所示:
  • ps:注意第一张图中的红色框框部分,如果修改为Thread.currentThread().getContextClassLoader()会发现实际上不会起作用,这是由于要想实现同一个类的不同版本的共存,这些不同的版本必须由不同的类加载器进行加载,因此就不能把这些类的加载工作委托给类加载器来完成,因为它们只有一份。

java自定义classloader引发的思考的更多相关文章

  1. 一次偶然的Java内存溢出引发的思考

    据说一次SQL查询返回太多数据,会引起服务器内存溢出. 不过,我现在碰到的情况是,调用一个Postgresql 存储过程,很复杂,那么在其中有很多raise notice这样的调试语句,如果碰巧有个死 ...

  2. Java Se:自定义ClassLoader

    JVM是如何知道java.lang包中的类的?JVM又是如何知道我们应用中的类的?我们的应用中明明是有某个类, 但是JVM却抛出ClassNotFoundException,这是为什么?XxxImpl ...

  3. JAVA 利用JNI加密class文件/自定义ClassLoader 类

    利用 JNI 对bytecode 加密.不影响java程序员的正常开发.09年的时候写的,现在拿出来晒晒————————————————————————————混淆才是王道,如果混淆再加密就更酷了.. ...

  4. 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考

    2018年12月12日18:44:53 一个ScheduledExecutorService启动的Java线程无故挂掉引发的思考 案件现场 不久前,在开发改造公司一个端到端监控日志系统的时候,出现了一 ...

  5. Java高级进阶:自定义ClassLoader

    假如我们的类不在classpath下,而我们又想读取一个自定义的目录下的class,如果做呢? 读取自定义目录的类 示例读取c:/test/com/test.jdk/Key.class这个类. pac ...

  6. 自定义classLoader思考

    jvm对于类实例的区分 基于完全限定名+classLoader 不同的classLoader可以加载同一class,生成不同实例, 但是这两个class实例生成的对象不能强转 spring boot ...

  7. Spring之LoadTimeWeaver——一个需求引发的思考---转

    原文地址:http://www.myexception.cn/software-architecture-design/602651.html Spring之LoadTimeWeaver——一个需求引 ...

  8. java lang(ClassLoader)

    一.什么是ClassLoader? 大家都知道,当我们写好一个Java程序之后,不是管是CS还是BS应用,都是由若干个.class文件组织而成的一个完整的Java应用程序,当程序在运行时,即会调用该程 ...

  9. 使用自定义 classloader 的正确姿势

    详细的原理就不多说了,网上一大把, 但是, 看了很多很多, 即使看了jdk 源码, 说了罗里吧嗦, 还是不很明白: 到底如何正确自定义ClassLoader, 需要注意什么 ExtClassLoade ...

随机推荐

  1. springboot(二十二)-sharding-jdbc-读写分离

    前面我们使用sharding-jdbc配置了分库分表.sharding-jdbc还有个用法,就是实现读写分离. 什么时候需要或者可以使用读写分离? 当我们的项目所使用的数据库查询的访问量,访问频率,及 ...

  2. CXF实现webService服务(一)

    以前工作中也用CXF,但都是用别人现成搭好的环境,这次自己重头搭建一遍环境.过程中也有遇到的问题,也做了简单的整理. 对于CXF是干什么用的,我不想多说,大家都知道这是我们在Java编程中webSer ...

  3. 使用python进行pdf文件分割

    Python代码 import os from pyPdf import PdfFileWriter, PdfFileReader def split(pdf_file, delta, output_ ...

  4. Python基础教程之dict和set

    1. dict Python中的dict等于js中的 map ,使用键-值(key-value)存储,具有极快的查找速度. 如果 我们要根据同学的姓名去查找他的成绩在不用dict的情况下.就需要两个l ...

  5. colaui基础

    监控 c-watch // 监控的方法函数 on 监控的参数名字 div(c-watch="fun on style" c-bind="styles") // ...

  6. dedecms body 输出自动替换结果。

    {dede:field.body function='str_replace("张三","李四",@me)'/} body内容中的张三全部换成了李四

  7. ActiveMQ基础01——Linux下载安装ActiveMQ

    1.下载 下载地址:http://activemq.apache.org/ 点击按钮 下载Linux下最新版安装包,点击即可下载 2.安装ActiveMQ 将之前下载的安装包上传到linux当中,一般 ...

  8. vue typescript curd

    用typescript 完成了一个页面 import { Component, Prop } from 'vue-property-decorator'; import Vue, { VNode } ...

  9. iQOO5G手机卡槽公布

    华为.中兴.一加.OPPO.vivo各自的5G手机相继拿到了3C强制认证,小米的也在路上,5G手机真的越来越近了. 今天,vivo iQOO还公布了其5G手机所用的卡槽样式,可以看到采用了双卡设计,同 ...

  10. Hibrenate实现根据实体类自动创建表或添加字段

    Hibernate支持自动建表,在开发阶段很方便,可以保证hbm与数据库表结构的自动同步. 实现: 在配置hibernate的配置文件中将hbm2ddl.auto设置为update,如:Xml代码&l ...