1.Javassist 简介
javassist是一个修改java字节码的开源库
下面是个很简单的例子,获取一个classPool,设置运行所需要的库,写入到对应位置
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{voidapply(Project project) {
project.logger.error("Dhjar start=========================")
project.extensions.create("dhjar", LJarConfig)
project.android.registerTransform(newJavassistTransform(project))
}
}
transform的几个方法
//获取输入类型jar或者class
@Overridepublic SetgetInputTypes() {returnTransformManager.CONTENT_CLASS;
}
//需要处理的范围, 主项目 子项目 或者三方库
@Overridepublic Set super QualifiedContent.Scope>getScopes() {
Set sets = new HashSet()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)returnsets;
}
@Override
Set super QualifiedContent.Scope>getReferencedScopes() {
Set sets = new HashSet()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
sets.add(QualifiedContent.Scope.PROVIDED_ONLY)returnsets
}
他的核心方法就是 分别为获取jar 和source目录
@Overridepublic void transform(TransformInvocation transformInvocation) throwsIOException {
}
下面就是捕获第三方异常的核心代码 通过插入一个相同的方法包裹上try catch 从而拦截需要捕获的方法, 具体代码可以看开头的链接
private static void modify(CtClass c, ClassPool mClassPool,Listmethods) {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= newStringBuffer()
sb.append("{try{")if(!ctMethod.getReturnType().getName().contains("void")){
sb.append("return ")
}
sb.append(method2)
sb.append("(")for(int i = 0; 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 或造成空指针崩溃
packagecom.vova.testlibrary;public classTestFile
{public intgetInt()
{return 1;
}public floatgetFloat()
{return 0.0F;
}public doublegetDoulbe()
{return 0.0D;
}public longgetLong()
{return 0L;
}public chargetChar()
{return 'a';
}public shortgetShort()
{return 0;
}public doublegetDouble()
{return 0.0D;
}publicString getString()
{
String aa= null;int len =aa.length();return null;
}public bytegetByte()
{return 0;
}
}
View Code
gradle编译效果图 输入test.jar 输出19.jar 打印需要替换的方法
下面是19.jar源码
packagecom.vova.testlibrary;importjava.io.PrintStream;public classTestFile
{public intgetIntDhCut()
{return 1;
}public floatgetFloatDhCut()
{return 0.0F;
}public doublegetDoulbe()
{return 0.0D;
}public longgetLongDhCut()
{return 0L;
}public chargetCharDhCut()
{return 'a';
}public shortgetShortDhCut()
{return 0;
}public doublegetDoubleDhCut()
{return 0.0D;
}publicString getStringDhCut()
{
String aa= null;int len =aa.length();return null;
}public bytegetByteDhCut()
{return 0;
}public intgetInt()
{try{returngetIntDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 0;
}public floatgetFloat()
{try{returngetFloatDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 0.0F;
}public longgetLong()
{try{returngetLongDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 0L;
}public chargetChar()
{try{returngetCharDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 'a';
}public shortgetShort()
{try{returngetShortDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 0;
}public doublegetDouble()
{try{returngetDoubleDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 0.0D;
}publicString getString()
{try{returngetStringDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return null;
}public bytegetByte()
{try{returngetByteDhCut();
}catch(Exception localException)
{
System.out.println(localException.toString());
localException.printStackTrace();
}return 0;
}
}
View Code