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 SetgetInputTypes() {
return TransformManager.CONTENT_CLASS;
}
//The scope to be processed, the main project, subproject or tripartite library
@Override
public Set super QualifiedContent.Scope>< span style="color: #000000;"> getScopes() {
Setsets = new HashSet ()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
return sets;
}
@Override
Set super QualifiedContent.Scope> getReferencedScopes() {
Setsets = 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,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 = 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
em>
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
p>
The following is the source code of 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
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 SetgetInputTypes() {
return TransformManager.CONTENT_CLASS;
}
//The scope to be processed, the main project, subproject or tripartite library
@Override
public Set super QualifiedContent.Scope>< span style="color: #000000;"> getScopes() {
Setsets = new HashSet ()
sets.add(QualifiedContent.Scope.EXTERNAL_LIBRARIES)
return sets;
}
@Override
Set super QualifiedContent.Scope> getReferencedScopes() {
Setsets = 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,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 = 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())
}
}
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;
}
}