引用

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. X-Forwarded-For伪造及防御

    使用x-Forward_for插件或者burpsuit可以改包,伪造任意的IP地址,使一些管理员后台绕过对IP地址限制的访问. 防护策略: 1.对于直接使用的 Web 应用,必须使用从TCP连接中得到 ...

  2. python CGI环境搭建

    本文web服务器使用的为apache. 1. 安装apache yum install -y httpd 2. 配置apache 修改apache配置文件/etc/httpd/conf/httpd.c ...

  3. Arch Linux 安装 ibus-rime

    参考网站 default.custom.yaml 在方案選單中添加五筆.雙拼 rime-wubi 操作方式 # 删除原rime(可选) sudo pacman -Rs ibus-rime ibus-t ...

  4. Pythonic Code In Several Lines

    1. Fibonacci Series def Fib(n): if n == 1 or n == 2: return 1; else: return Fib(n - 1) + Fib(n - 2) ...

  5. 【基础操作】博弈论 / SG 函数详解

    博弈死我了……(话说哪个小学生会玩博弈论提到的这类弱智游戏,还取石子) 先推荐两个文章链接:浅谈算法——博弈论(从零开始的博弈论) 博弈论相关知识及其应用 This article was updat ...

  6. linux服务器上如何使用nginx访问本地静态资源

    查看80端口是否被占用,一般80端口多被apache服务占用. netstat -anp|grep 80 2.修改apache服务的端口号 vim /etc/apache2/ports.conf 3. ...

  7. 调试python 程序的几种方法总结

    程序能一次写完并正常运行的概率很小,基本不超过1%.总会有各种各样的bug需要修正.有的bug很简单,看看错误信息就知道,有的bug很复杂,我们需要知道出错时,哪些变量的值是正确的,哪些变量的值是错误 ...

  8. 前端杂谈: Attribute VS Property

    前端杂谈: Attribute VS Property 第一个问题: 什么是 attribute & 什么是 property ? attribute 是我们在 html 代码中经常看到的键值 ...

  9. mysql创建函数槽点

    上机环境 mysql8.0 navicat for mysql 很有那么一批软件程序,要不做点脱了裤子放屁的事儿就觉得自己不够二进制似的,今儿写了一下午mysql函数,怎么都通过不了,上网一看 mys ...

  10. tornado下pandas ndarray乱试

    from tornado.web import RequestHandler from pymongo import MongoClient import pandas,xlrd from panda ...