专栏首页Phoenix的Android之旅关于ClassLoader还可以这么做

关于ClassLoader还可以这么做

庖丁解牛--自定义ClassLoader

上次我们说到Java的双亲委托机制,导致我们不能加载到WangHouse里的Socker类。今天我们来说说怎么在不改变目录结构的情况下加载Socker。

自定义ClassLoader

自定义ClassLoader可能比较陌生。既然我们知道AppClassLoader是对应当前的classpath,而ClassLoader会根据class path来加载类,那么我们可以再自定义一个ClassLoader,将它的路径指定到WangHouse。 自定义ClassLoader分两步 · 继承 java.lang.ClassLoader · 重写 findClass方法

这里需要说一下为什么只重写findClass方法。JDK在搜索类的时候,会先调用 loadClass,在找不到的时候会调用 findClass,虽然重写loadClass()方法也可以,但是这样会改写原有的正常查找逻辑,因此我们只需要重写findClass()就可以,这是Java预留给开发者的可重载方法。

public class DiskClassLoader extends ClassLoader {

    private String mFilePath;

    public DiskClassLoader(String mFilePath) {
        this.mFilePath = mFilePath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String fileName = getFileName(name);
        File file = new File(mFilePath, fileName);
        try {
            FileInputStream ins = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            int len = 0;
            try {
                while((len = ins.read()) != -1) {
                    bos.write(len);
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            byte[] data = bos.toByteArray();
            ins.close();
            bos.close();
            return defineClass(name, data, 0, data.length);
        } catch (IOException exp) {
            exp.printStackTrace();
        }
        return super.findClass(name);
    }

    private String getFileName(String name){
        int index = name.lastIndexOf('.');
        if(index == -1) {
            return name + ".class";
        } else {
            return name.substring(index) + ".class";
        }
    }
}

简单的解释代码的逻辑是在传进去的路径下查找对应的class文件,把它转换为文件流,通过ClassLoader的 defineClass方法获得Class对象。

用自定义Loader来加载class

现在我们有可以找class的工具了,目标的类Socker在隔壁WangHouse,调用的代码这么写

public class Ming {

  public static void main(String[] args) {
    System.out.println("Ming looking for socker");
    findSocker();
  }

  private static void findSocker() {
    DiskClassLoader loader = new DiskClassLoader("../WangHouse/");
    try {
      Class b = loader.loadClass("Socker");
      if(b != null){
        try {
          Object object = b.newInstance();
          Method method = b.getDeclaredMethod("callSockerMethod", null);
          method.invoke(object, null);
        } catch(Exception e) {
          e.printStackTrace();
        }
      }

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

运行结果

$ java Ming Ming looking for socker Socker method invoke

看到这里肯定会有疑问,为什么要用反射。我们接着说。

举一反三

为什么要用反射来获取Socker对象?既然都能找到类,也已经加载进来了,为何不直接 new 就完了?

其实很简单,因为Ming和Socker并不在同一个ClassLoader里,Ming在AppClassLoader中,而Socker我们加载到了DiskClassLoader里。子Loader加载类的时候可以去父Loader里找到,就像我们调用System,而父Loader用子Loader里的类的时候是不行的,只能用反射。

…可能有人已经意识到,Android的热修复是不是可以用自定义ClassLoader来做? 没错!有些热修复方案就是基于ClassLoader做的。 明天我们接着讲开发中时常遇到的ClassCastException。在我们准备好相关的点之后,就可以自己来写一个热修复框架了。

本文分享自微信公众号 - Android每日一讲(gh_f053f29083b9),作者:Phoenix

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java的克隆

    说到克隆,本质都是使用一个已经实例化完成的对象的副本。 对于基本类型比较简单。比方说我们想复制一个变量,

    PhoenixZheng
  • 多说两句关于ClassLoader的面试题

    Java的高级知识中ClassLoader是很重要的一环。面试中有很多关于ClassLoader的问题,今天分析一道例子。

    PhoenixZheng
  • 被压榨的程序员--曾经以为买不起房还能租,现在连房也租不起了

    作为最悲催的80后90后,毕业的时候刚好赶上房价大涨。工作几年,刚学会理财,又被15年的A股收割了一波。想换便宜点的房子住,却发现连城中村也要2000多一个月。...

    PhoenixZheng
  • 经典笔试题-iframe,Frame中Session丢失的解决方法

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    cwl_java
  • 我所理解的Remoting(2):远程对象生命周期的管理[上篇]

    1.CLR的垃圾回收机制 在.NET中提到对象的生命周期,我们会不由自主地想到CLR的垃圾回收。在运行一个.NET程序过程中,我们通过某种方式,比如通过new操...

    蒋金楠
  • Mac终端给命令设置别名alias的办法

    在Mac里使用curl https://www.google.com,运行后得不到期望看到的google首页的HTML source code。

    Jerry Wang
  • ESP8266学习笔记7:保存和读取自定义参数

    这几天正在使用ESP8266接入机智云,需要保存一些自定义的参数。在笔记6中,做了AP信息的保存,但它是借助特定的API保存特定的AP信息。而自定义的参数还需要...

    twowinter
  • 从零开始学 Web 之 DOM(三)innerText与innerHTML、自定义属性

    Daotin
  • Java学习笔记第一篇:坦克大战游戏

    一、Java学习笔记系列 笔者大学时候学的编程语言是C和汇编,毕业以后并未从事过开发工作,也没有接触过Java。但近两年的PaaS、CI/CD主要是以Java应...

    魏新宇
  • 为你的wordpress网站添加[活跃访客榜],瞬间提升网站访客人气500%

    据不完全统计,全世界大约有60%左右的网站都是采用的wordpress建设的。那么我们如何来提高自己网站的人气访客啦,近期我也在自己的网站上做了这样一个功能,就...

    wordpress建站吧

扫码关注云+社区

领取腾讯云代金券