Android implements a third-party library exception with javassist

Git Portal

Android development will inevitably use a lot of third-party libraries. If you encounter an exception, you often have the idea of ​​having more than enough energy but not enough energy. At the same day, if it is open source, you can use the source code Import and modify,

But it will inevitably lead to poor maintainability. This article provides an idea of ​​catching third-party library exceptions. It can also be extended to modify third-party code at compile time to insert your own needs

1. Introduction to Javassist

javassist is an open source library that modifies java bytecode

The following is a very simple example, get a classPool, set it to run The required library is written to the corresponding location

For specific syntax, please refer to Javassist introduction

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

cc.setSuperclass(pool.get(
"test.Point"));
cc.writeFile();

2. Application in Android

Gradle compiling Android projects is executed through tasks one by one Task, we can see a lot of transform* tasks through gradle

Insert a transform of your own at compile time to realize the interception of source code or third-party jar libraries and modify third-party libraries

Below define a gradle plug-in, register a transform of your own

public class MainPlugin implements Plugin{

void apply(Project project) {
project.logger.error(
"Dhjar start=========================")
project.extensions.create(
"dhjar", LJarConfig)
project.android.registerTransform(
new JavassistTransform(project))
}
}

Several methods of transform

//Get the input type jar or class 
@Override
public Set getInputTypes() {
return TransformManager.CONTENT_CLASS;
}
//The scope to be processed, the main project, subproject or tripartite library
@Override
public Setsuper QualifiedContent.Scope>< span style="color: #000000;"> getScopes() {
Set sets = new HashSet()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
return sets;
}
@Override
Set
super QualifiedContent.Scope> getReferencedScopes() {
Set
sets = new HashSet()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
sets.add(QualifiedContent.Scope.PROVIDED_ONLY)
return sets
}

His core method is to obtain jar and source directories respectively

 @Override

public void transform(TransformInvocation transformInvocation) throws IOException {
}


The following is the core code for catching third-party exceptions by inserting the same method to wrap the try catch to intercept what needs to be caught For the specific code, please refer to the link at the beginning
 private static void modify(CtClass c, ClassPool mClassPool,List 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){
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())
}
}

 The class before interception At this time, we directly call getString or cause a null pointer crash
share picture

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 compilation renderings input test.jar output 19.jar Print method that needs to be replaced

share picture

p>

The following is the source code of 19.jar
Share picture

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

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

cc.setSuperclass(pool.get(
"test.Point"));
cc.writeFile();

public class MainPlugin implements Plugin{

void apply(Project project) {
project.logger.error(
"Dhjar start=========================")
project.extensions.create(
"dhjar", LJarConfig)
project.android.registerTransform(
new JavassistTransform(project))
}
}

//Get input type jar or class 
@Override
public Set getInputTypes() {
return TransformManager.CONTENT_CLASS;
}
//The scope to be processed, the main project, subproject or tripartite library
@Override
public Setsuper QualifiedContent.Scope>< span style="color: #000000;"> getScopes() {
Set sets = new HashSet()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
return sets;
}
@Override
Set
super QualifiedContent.Scope> getReferencedScopes() {
Set
sets = new HashSet()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
sets.add(QualifiedContent.Scope.PROVIDED_ONLY)
return sets
}

 @Override

public void transform(TransformInvocation transformInvocation) throws IOException {
}

 private static void modify(CtClass c, ClassPool mClassPool,List 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){
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())
}
}

share picture

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

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;
}
}

分享图片

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

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;
}
}

Leave a Comment

Your email address will not be published.