
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 或造成空指针崩溃@H_403_234@
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 总结
以上是内存溢出为你收集整理的android用 javassist实现捕获第三方库异常全部内容,希望文章能够帮你解决android用 javassist实现捕获第三方库异常所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)