Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 463|回复: 0

android用 javassist实现捕获第三方库异常

[复制链接]
  • TA的每日心情
    奋斗
    昨天 22:10
  • 签到天数: 756 天

    [LV.10]以坛为家III

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    707560
    发表于 2021-8-30 13:47:37 | 显示全部楼层 |阅读模式

    Git传送门

    Android开发中不可避免的会用到很多第三方库, 如果碰到异常 常常有种心有余而力不足的想法,如果是开源的 你可以吧源码导入进来进行修改,但不可避免的会造成维护性差, 本文提供一个捕获屏蔽第三方库异常的思路,也可以扩展为在编译时修改第三方库代码,从而插入自己的需求

    1.Javassist 简介

      javassist是一个修改java字节码的开源库

     下面是个很简单的例子,获取一个classPool,设置运行所需要的库,写入到对应位置

     具体语法可以参考 Javassist介绍

    ClassPool pool = ClassPool.getDefault();
    pool.insertClassPath("/usr/local/javalib");
    CtClass cc = pool.get("test.Rectangle");
    cc.setSuperclass(pool.get("test.Point"));
    cc.writeFile();

     2.在安卓中的应用

     gradle 编译安卓项目是通过一个个task来执行任务, 我们可以通过gradle看到很多transform*的task

     在编译时插入一个自己的transform 从而实现对源码或第三方jar库拦截 实现修改第三方库

    下面时定义一个gradle插件, 注册一个自己的transform

    public class MainPlugin implements Plugin<Project>{
        void apply(Project project) {
            project.logger.error("Dhjar start=========================")
            project.extensions.create("dhjar", LJarConfig)
            project.android.registerTransform(new JavassistTransform(project))
        }
    }

    transform的几个方法 

    //获取输入类型jar或者class  
    @Override
    public Set<QualifiedContent.ContentType> getInputTypes() { return TransformManager.CONTENT_CLASS; } //需要处理的范围, 主项目 子项目 或者三方库 @Override public Set<? super QualifiedContent.Scope> getScopes() { Set<QualifiedContent.Scope> sets = new HashSet<QualifiedContent.Scope>() sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES) return sets; } @Override Set<? super QualifiedContent.Scope> getReferencedScopes() { Set<QualifiedContent.Scope> sets = new HashSet<QualifiedContent.Scope>() sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES) sets.add(QualifiedContent.Scope.PROVIDED_ONLY) return sets }

     

    他的核心方法就是  分别为获取jar 和source目录

        @Override
        public void transform(TransformInvocation transformInvocation) throws IOException {
    }

    下面就是捕获第三方异常的核心代码 通过插入一个相同的方法包裹上try catch 从而拦截需要捕获的方法, 具体代码可以看开头的链接
        private static void modify(CtClass c, ClassPool mClassPool,List<String> methods) {
            if (c.isFrozen()) {
                c.defrost()
            }
            System.out.println("find class==============="+c.getName())
            for(String method : methods){
                CtMethod ctMethod = c.getDeclaredMethod(method)
                String method2 = method+"DhCut"
                CtMethod ctMethod2 = CtNewMethod.copy(ctMethod,method2,c,null)
                c.addMethod(ctMethod2)
                int methodLen = ctMethod.getParameterTypes().length
                StringBuffer sb  = new StringBuffer()
                sb.append("{try{")
                if(!ctMethod.getReturnType().getName().contains("void")){
                    sb.append("return ")
                }
                sb.append(method2)
                sb.append("(")
                for(int i = 0; i<methodLen;i++){
                    sb.append("\$"+(i+1))
                    if(i!=methodLen-1){
                        sb.append(",")
                    }
                }
                sb.append(");}catch(Exception ex){ System.out.println(ex.toString());ex.printStackTrace();}")
                if(!ctMethod.getReturnType().getName().contains("void")){
                    sb.append("return ")
                    String result = getReturnValue(ctMethod.getReturnType().getName())
                    sb.append(result)
                    sb.append(";")
                }
                sb.append("}")
               System.out.println("return type  =======" +ctMethod.getReturnType().getName())
                ctMethod.setBody(sb.toString())
            }
        }

     

     拦截前得类 此时我们直接调用getString 或造成空指针崩溃
    package com.vova.testlibrary;
    
    public class TestFile
    {
      public int getInt()
      {
        return 1;
      }
      
      public float getFloat()
      {
        return 0.0F;
      }
      
      public double getDoulbe()
      {
        return 0.0D;
      }
      
      public long getLong()
      {
        return 0L;
      }
      
      public char getChar()
      {
        return 'a';
      }
      
      public short getShort()
      {
        return 0;
      }
      
      public double getDouble()
      {
        return 0.0D;
      }
      
      public String getString()
      {
        String aa = null;
        int len = aa.length();
        return null;
      }
      
      public byte getByte()
      {
        return 0;
      }
    }
    View Code

     

       gradle编译效果图   输入test.jar   输出19.jar  打印需要替换的方法

    下面是19.jar源码
    package com.vova.testlibrary;
    
    import java.io.PrintStream;
    
    public class TestFile
    {
      public int getIntDhCut()
      {
        return 1;
      }
      
      public float getFloatDhCut()
      {
        return 0.0F;
      }
      
      public double getDoulbe()
      {
        return 0.0D;
      }
      
      public long getLongDhCut()
      {
        return 0L;
      }
      
      public char getCharDhCut()
      {
        return 'a';
      }
      
      public short getShortDhCut()
      {
        return 0;
      }
      
      public double getDoubleDhCut()
      {
        return 0.0D;
      }
      
      public String getStringDhCut()
      {
        String aa = null;
        int len = aa.length();
        return null;
      }
      
      public byte getByteDhCut()
      {
        return 0;
      }
      
      public int getInt()
      {
        try
        {
          return getIntDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 0;
      }
      
      public float getFloat()
      {
        try
        {
          return getFloatDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 0.0F;
      }
      
      public long getLong()
      {
        try
        {
          return getLongDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 0L;
      }
      
      public char getChar()
      {
        try
        {
          return getCharDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 'a';
      }
      
      public short getShort()
      {
        try
        {
          return getShortDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 0;
      }
      
      public double getDouble()
      {
        try
        {
          return getDoubleDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 0.0D;
      }
      
      public String getString()
      {
        try
        {
          return getStringDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return null;
      }
      
      public byte getByte()
      {
        try
        {
          return getByteDhCut();
        }
        catch (Exception localException)
        {
          System.out.println(localException.toString());
          localException.printStackTrace();
        }
        return 0;
      }
    }
    View Code

     

     
    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-6-28 18:35 , Processed in 0.067676 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表