引用

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页面模板thymeleaf的简单用法

    thymeleaf基础语法: 变量输出与字符串操作: ​ th:text 表示在页面输出值 ​ th:value 表示将一个值放入input标签的value中 判断字符串是否为空: ​ thymele ...

  2. Action注入错误

    2016-07-13 13:52:09,584 [ERROR]-[com.opensymphony.xwork2.util.logging.commons.CommonsLogger:38] Exce ...

  3. struts.xml中package标签的子标签及顺序

    记录一下:

  4. openlayers之地图截图

    方法1 //this.map._this为初始化地图对象 this.map._this.once('postcompose', function (event) { var canvas = even ...

  5. 配置Linux静态IP地址

  6. linux命令详解——ftp

    ftp服务器在网上较为常见,Linux ftp命令的功能是用命令的方式来控制在本地机和远程机之间传送文件,这里详细介绍Linux ftp命令的一些经常使用的命令,相信掌握了这些使用Linux 进行ft ...

  7. Delphi 键盘的编程

  8. jQuery获取当前按钮的id

    function test(e) { $(e.target).attr('id') } // 记得带上点击事件

  9. MXNetError: [05:53:50] src/operator/nn/./cudnn/cudnn_convolution-inl.h:287

    insightface train.py 报错:mxnet.base.MXNetError: [05:53:50] src/operator/nn/./cudnn/cudnn_convolution- ...

  10. 【hdu 6155】Subsequence Count

    题意 给定一个 \(01\) 串 \(S_{1...n}\) 和 \(Q\) 个操作. 操作有 \(2\) 种类型: 1. 将 \([l,r]\) 区间所有数取反(\(0→1,\space 1→0\) ...