diff --git a/app/src/main/java/com/meituan/sample/MainActivity.java b/app/src/main/java/com/meituan/sample/MainActivity.java
index 653fe775..ac1792a4 100644
--- a/app/src/main/java/com/meituan/sample/MainActivity.java
+++ b/app/src/main/java/com/meituan/sample/MainActivity.java
@@ -49,6 +49,8 @@ public class MainActivity extends AppCompatActivity {
Hll hll = new Hll(false);
+
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -104,27 +106,28 @@ public void onClick(View v) {
e.printStackTrace();
}
- System.out.println(" run(String x) "+run("robust ",123));
- System.out.println(" run(People x) "+run(new People(),123d));
- System.out.println(" run(float x) "+run(123f));
- System.out.println(" double run() "+run());
+ System.out.println(" run(String x) " + run("robust ", 123));
+ System.out.println(" run(People x) " + run(new People(), 123d));
+ System.out.println(" run(float x) " + run(123f));
+ System.out.println(" double run() " + run());
System.out.println("in MainActivity end ");
}
-
- private String run(String x,int p){
- return x+"meituan";
+ private String run(String x, int p) {
+ return x + "meituan";
}
- private String run(People x,double d){
+
+ private String run(People x, double d) {
x.setAddr("meituan");
return x.getAddr();
}
- private int run(float x){
- return (int)x;
+
+ private int run(float x) {
+ return (int) x;
}
- private double run(){
+ private double run() {
return 1d;
}
diff --git a/app/src/main/java/com/meituan/sample/robusttest/Super.java b/app/src/main/java/com/meituan/sample/robusttest/Super.java
index 8b3416ab..14fb3613 100644
--- a/app/src/main/java/com/meituan/sample/robusttest/Super.java
+++ b/app/src/main/java/com/meituan/sample/robusttest/Super.java
@@ -28,7 +28,6 @@ public class Super extends Hll {
}
-
public String[] methodWithArrayParameters(String[] flag) {
return flag;
}
diff --git a/app/src/main/java/com/meituan/sample/robusttest/other/Hll.java b/app/src/main/java/com/meituan/sample/robusttest/other/Hll.java
index a477ecf6..66933073 100644
--- a/app/src/main/java/com/meituan/sample/robusttest/other/Hll.java
+++ b/app/src/main/java/com/meituan/sample/robusttest/other/Hll.java
@@ -23,6 +23,7 @@ public Hll(boolean t) {
public Hll() {
}
+
private String privateMethod(int index, String name) {
Log.d("robust", "in hll.getStrings() ");
packageMethod(1,name);
diff --git a/autopatchbase/src/main/java/com/meituan/robust/patch/RobustModify.java b/autopatchbase/src/main/java/com/meituan/robust/patch/RobustModify.java
index ae06be22..e9a51ebb 100644
--- a/autopatchbase/src/main/java/com/meituan/robust/patch/RobustModify.java
+++ b/autopatchbase/src/main/java/com/meituan/robust/patch/RobustModify.java
@@ -2,6 +2,8 @@
/**
* Created by mivanzhang on 16/12/9.
+ *
+ * A backup for annotation Modify, in some situation Modify will not work, such as Generic
*/
public final class RobustModify {
diff --git a/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Add.java b/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Add.java
index 03eddf46..856dd3fb 100644
--- a/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Add.java
+++ b/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Add.java
@@ -8,6 +8,8 @@
/**
* Created by mivanzhang on 16/12/19.
+ * 用来标记新增的类和方法
+ * annotaion used for add classes or methods,classes and methods will be packed into patch.jar/patch.apk
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.CONSTRUCTOR})
diff --git a/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Modify.java b/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Modify.java
index 14fecd6a..5c35014f 100644
--- a/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Modify.java
+++ b/autopatchbase/src/main/java/com/meituan/robust/patch/annotaion/Modify.java
@@ -8,6 +8,7 @@
/**
* Created by mivanzhang on 16/12/9.
+ * annotaion used for modify classes or methods,classes and methods will be packed into patch.jar/patch.apk
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.CLASS)
diff --git a/autopatchbase/src/main/java/com/meituan/robust/utils/EnhancedRobustUtils.java b/autopatchbase/src/main/java/com/meituan/robust/utils/EnhancedRobustUtils.java
index 22145346..3f96b00e 100644
--- a/autopatchbase/src/main/java/com/meituan/robust/utils/EnhancedRobustUtils.java
+++ b/autopatchbase/src/main/java/com/meituan/robust/utils/EnhancedRobustUtils.java
@@ -7,6 +7,8 @@
/**
* Created by mivanzhang on 16/8/15.
+ *
+ * A reflect utility class, providing methods for reflecting methods and set/get fields
*/
public class EnhancedRobustUtils {
public static boolean isThrowable = true;
diff --git a/build.gradle b/build.gradle
index 7b9de258..85388b4c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -9,8 +9,8 @@ buildscript {
classpath 'com.android.tools.build:gradle:2.1.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
- classpath 'com.meituan.robust:gradle-plugin:0.4.5'
- classpath 'com.meituan.robust:auto-patch-plugin:0.4.5'
+ classpath 'com.meituan.robust:gradle-plugin:0.4.7'
+ classpath 'com.meituan.robust:auto-patch-plugin:0.4.7'
classpath 'me.tatarka:gradle-retrolambda:3.2.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/InsertcodeStrategy.java b/gradle-plugin/src/main/groovy/robust/gradle/plugin/InsertcodeStrategy.java
index 6739c38b..cee29cf7 100644
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/InsertcodeStrategy.java
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/InsertcodeStrategy.java
@@ -18,13 +18,23 @@
*/
public abstract class InsertcodeStrategy {
- protected List hotfixPackageList = new ArrayList<>();
- protected List hotfixMethodList = new ArrayList<>();
- protected List exceptPackageList = new ArrayList<>();
- protected List exceptMethodList = new ArrayList<>();
- protected boolean isHotfixMethodLevel = false;
- protected boolean isExceptMethodLevel = false;
+ //packnames need to be insert code 需要插桩的包名列表,
+ protected List hotfixPackageList = new ArrayList<>();
+ //methods list need to insert code 需要插桩的方法列表
+ protected List hotfixMethodList = new ArrayList<>();
+
+ //packnames don`t need to be insert code 不需要插桩的包名列表,
+ protected List exceptPackageList = new ArrayList<>();
+
+ //methods list do not need to insert code 不需要插桩的方法列表
+ protected List exceptMethodList = new ArrayList<>();
+ //a switch control whether need to filter method in hotfixMethodList, if false ,hotfixMethodList will be ignored
+ protected boolean isHotfixMethodLevel = false;
+
+ //a switch control whether need to filter method in exceptMethodList, if false ,exceptMethodList will be ignored
+ protected boolean isExceptMethodLevel = false;
protected AtomicInteger insertMethodCount = new AtomicInteger(0);
+ //record every method with unique method number
public HashMap methodMap = new HashMap();
public InsertcodeStrategy(List hotfixPackageList, List hotfixMethodList, List exceptPackageList, List exceptMethodList, boolean isHotfixMethodLevel, boolean isExceptMethodLevel) {
@@ -37,8 +47,16 @@ public InsertcodeStrategy(List hotfixPackageList, List hotfixMet
insertMethodCount.set(0);
}
+ /**
+ * @param box all classes which will be packed into apk,所有需要打入apk中的类
+ * @param jarFile 所有的插桩处理过的class都会被输出的jarFile
+ * @throws CannotCompileException
+ * @throws IOException
+ * @throws NotFoundException
+ */
protected abstract void insertCode(List box, File jarFile) throws CannotCompileException, IOException, NotFoundException;
- protected boolean isNeedInsertClass(String className) {
+
+ protected boolean isNeedInsertClass(String className) {
//这样子可以在需要埋点的剔除指定的类
for (String exceptName : exceptPackageList) {
@@ -54,14 +72,14 @@ protected boolean isNeedInsertClass(String className) {
return false;
}
- protected void zipFile(byte[] classBytesArray, ZipOutputStream zos, String entryName){
+ protected void zipFile(byte[] classBytesArray, ZipOutputStream zos, String entryName) {
try {
ZipEntry entry = new ZipEntry(entryName);
zos.putNextEntry(entry);
zos.write(classBytesArray, 0, classBytesArray.length);
zos.closeEntry();
zos.flush();
- }catch (Exception e){
+ } catch (Exception e) {
e.printStackTrace();
}
}
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashAction.groovy b/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashAction.groovy
index a6ba12f3..9dc17133 100755
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashAction.groovy
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashAction.groovy
@@ -8,6 +8,8 @@ import java.security.MessageDigest
/**
* Created by hedex on 17/2/14.
+ *
+ * calculate unique string for each apk,you can get the string in file located in build/outputs/robust/robust.apkhash
*/
class RobustApkHashAction implements Action {
@Override
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashZipUtils.groovy b/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashZipUtils.groovy
index 9ad565c9..baeeba8e 100755
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashZipUtils.groovy
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustApkHashZipUtils.groovy
@@ -3,6 +3,7 @@ package robust.gradle.plugin
import com.meituan.robust.Constants
import java.util.zip.*
+
/**
* Created by hedex on 17/2/14.
*/
@@ -82,7 +83,7 @@ class RobustApkHashZipUtils {
while (entries.hasMoreElements()) {
// ZipEntry zipEntry = entries.nextElement();//保守
ZipEntry zipEntry = new ZipEntry(entries.nextElement().name);
- if (null != zipEntry ) {
+ if (null != zipEntry) {
addZipEntry(zipOutputStream, zipEntry, apZipFile.getInputStream(zipEntry))
}
}
@@ -116,7 +117,6 @@ class RobustApkHashZipUtils {
return crc.getValue();
}
-
/**
* add zip entry
*
@@ -125,7 +125,8 @@ class RobustApkHashZipUtils {
* @param inputStream
* @throws Exception
*/
- private static void addZipEntry(ZipOutputStream zipOutputStream, ZipEntry zipEntry, InputStream inputStream) throws Exception {
+ private
+ static void addZipEntry(ZipOutputStream zipOutputStream, ZipEntry zipEntry, InputStream inputStream) throws Exception {
try {
zipOutputStream.putNextEntry(zipEntry);
byte[] buffer = new byte[1024];
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustTransform.groovy b/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustTransform.groovy
index e768c175..fee26dfc 100644
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustTransform.groovy
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/RobustTransform.groovy
@@ -40,7 +40,7 @@ class RobustTransform extends Transform implements Plugin {
robust = new XmlSlurper().parse(new File("${project.projectDir}/${Constants.ROBUST_XML}"))
logger = project.logger
initConfig()
- //turnOnDevelopModel 是true的话,则强制执行插入
+ //isForceInsert 是true的话,则强制执行插入
if (!isForceInsert) {
def taskNames = project.gradle.startParameter.taskNames
def isDebugTask = false;
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/AsmInsertImpl.java b/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/AsmInsertImpl.java
index 22c64a5a..9e375c75 100644
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/AsmInsertImpl.java
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/AsmInsertImpl.java
@@ -34,6 +34,8 @@
/**
* Created by zhangmeng on 2017/5/10.
+ *
+ * insert code using asm
*/
public class AsmInsertImpl extends InsertcodeStrategy {
@@ -45,12 +47,15 @@ public AsmInsertImpl(List hotfixPackageList, List hotfixMethodLi
@Override
protected void insertCode(List box, File jarFile) throws IOException, CannotCompileException {
- ZipOutputStream outStream=new JarOutputStream(new FileOutputStream(jarFile));
- for(CtClass ctClass:box) {
+ ZipOutputStream outStream = new JarOutputStream(new FileOutputStream(jarFile));
+ //get every class in the box ,ready to insert code
+ for (CtClass ctClass : box) {
+ //change modifier to public ,so all the class in the apk will be public ,you will be able to access it in the patch
ctClass.setModifiers(AccessFlag.setPublic(ctClass.getModifiers()));
- if(isNeedInsertClass(ctClass.getName())&&!(ctClass.isInterface() || ctClass.getDeclaredMethods().length < 1)) {
+ if (isNeedInsertClass(ctClass.getName()) && !(ctClass.isInterface() || ctClass.getDeclaredMethods().length < 1)) {
+ //only insert code into specific classes
zipFile(transformCode(ctClass.toBytecode(), ctClass.getName().replaceAll("\\.", "/")), outStream, ctClass.getName().replaceAll("\\.", "/") + ".class");
- }else {
+ } else {
zipFile(ctClass.toBytecode(), outStream, ctClass.getName().replaceAll("\\.", "/") + ".class");
}
@@ -58,65 +63,69 @@ protected void insertCode(List box, File jarFile) throws IOException, C
outStream.close();
}
- private class InsertMethodBodyAdapter extends ClassVisitor implements Opcodes {
+ private class InsertMethodBodyAdapter extends ClassVisitor implements Opcodes {
public InsertMethodBodyAdapter() {
super(Opcodes.ASM5);
}
+
ClassWriter classWriter;
private String className;
//this maybe change in the future
- private Map methodInstructionTypeMap;
- public InsertMethodBodyAdapter(ClassWriter cw,String className, Map methodInstructionTypeMap) {
- super(Opcodes.ASM5,cw);
- this.classWriter =cw;
- this.className=className;
- this.methodInstructionTypeMap=methodInstructionTypeMap;
- classWriter.visitField(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC, Constants.INSERT_FIELD_NAME, Type.getDescriptor(ChangeQuickRedirect.class), null, null);
+ private Map methodInstructionTypeMap;
+
+ public InsertMethodBodyAdapter(ClassWriter cw, String className, Map methodInstructionTypeMap) {
+ super(Opcodes.ASM5, cw);
+ this.classWriter = cw;
+ this.className = className;
+ this.methodInstructionTypeMap = methodInstructionTypeMap;
+ //insert the field
+ classWriter.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, Constants.INSERT_FIELD_NAME, Type.getDescriptor(ChangeQuickRedirect.class), null, null);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- if(isProtect(access)) {
+ if (isProtect(access)) {
access = setPublic(access);
}
- //
MethodVisitor mv = super.visitMethod(access, name,
desc, signature, exceptions);
- if (!isQualifiedMethod(access,name,desc,methodInstructionTypeMap)) {
+ if (!isQualifiedMethod(access, name, desc, methodInstructionTypeMap)) {
return mv;
}
- StringBuilder parameters=new StringBuilder();
- Type[]types=Type.getArgumentTypes(desc);
- for(Type type:types){
+ StringBuilder parameters = new StringBuilder();
+ Type[] types = Type.getArgumentTypes(desc);
+ for (Type type : types) {
parameters.append(type.getClassName()).append(",");
}
- if(parameters.length() > 0 && parameters.charAt(parameters.length()-1)==','){
- parameters.deleteCharAt(parameters.length()-1);
+ //remove the last ","
+ if (parameters.length() > 0 && parameters.charAt(parameters.length() - 1) == ',') {
+ parameters.deleteCharAt(parameters.length() - 1);
}
+ //record method number
+ methodMap.put(className.replace('/', '.') + "." + name + "(" + parameters.toString() + ")", insertMethodCount.incrementAndGet());
+ return new MethodBodyInsertor(mv, className, desc, isStatic(access), String.valueOf(insertMethodCount.get()), name, access);
+ }
- methodMap.put(className.replace('/','.')+"."+name+"("+parameters.toString()+")", insertMethodCount.incrementAndGet());
- return new MethodBodyInsertor(mv,className,desc,isStatic(access), String .valueOf(insertMethodCount.get()),name,access);
+ private boolean isProtect(int access) {
+ return (access & Opcodes.ACC_PROTECTED) != 0;
}
- private boolean isProtect(int access) {
- return (access & Opcodes.ACC_PROTECTED) != 0;
- }
+ private int setPublic(int access) {
+ return (access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) | Opcodes.ACC_PUBLIC;
+ }
- private int setPublic(int access){
- return (access & ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) | Opcodes.ACC_PUBLIC;
- }
- private boolean isQualifiedMethod(int access, String name, String desc,Map methodInstructionTypeMap) {
+ private boolean isQualifiedMethod(int access, String name, String desc, Map c) {
//类初始化函数和构造函数过滤
- if(AsmUtils.CLASS_INITIALIZER.equals(name)||AsmUtils.CONSTRUCTOR.equals(name)){
+ if (AsmUtils.CLASS_INITIALIZER.equals(name) || AsmUtils.CONSTRUCTOR.equals(name)) {
return false;
}
//@warn 这部分代码请重点review一下,判断条件写错会要命
//这部分代码请重点review一下,判断条件写错会要命
// synthetic 方法暂时不aop 比如AsyncTask 会生成一些同名 synthetic方法,对synthetic 以及private的方法也插入的代码,主要是针对lambda表达式
- if(((access& Opcodes.ACC_SYNTHETIC) != 0)&&((access & Opcodes.ACC_PRIVATE)==0)){
+ if (((access & Opcodes.ACC_SYNTHETIC) != 0) && ((access & Opcodes.ACC_PRIVATE) == 0)) {
return false;
}
if ((access & Opcodes.ACC_ABSTRACT) != 0) {
@@ -150,10 +159,9 @@ private boolean isQualifiedMethod(int access, String name, String desc,Map paramsTypeClass=new ArrayList();
+ List paramsTypeClass = new ArrayList();
boolean isStatic;
//目前methodid是int类型的,未来可能会修改为String类型的,这边进行了一次强转
String methodId;
- public MethodBodyInsertor(MethodVisitor mv,String className, String desc, boolean isStatic,String methodId,String name,int access) {
+ public MethodBodyInsertor(MethodVisitor mv, String className, String desc, boolean isStatic, String methodId, String name, int access) {
super(Opcodes.ASM5, mv, access, name, desc);
- this.className=className;
- this.returnType =Type.getReturnType(desc);
+ this.className = className;
+ this.returnType = Type.getReturnType(desc);
Type[] argsType = Type.getArgumentTypes(desc);
for (Type type : argsType) {
paramsTypeClass.add(type);
}
- this.isStatic=isStatic;
- this.methodId =methodId;
+ this.isStatic = isStatic;
+ this.methodId = methodId;
}
@Override
public void visitCode() {
- RobustAsmUtils.createInsertCode(this,className,paramsTypeClass, returnType,isStatic,Integer.valueOf(methodId));
+ //insert code here
+ RobustAsmUtils.createInsertCode(this, className, paramsTypeClass, returnType, isStatic, Integer.valueOf(methodId));
}
}
- private boolean isStatic(int access){
+
+ private boolean isStatic(int access) {
return (access & Opcodes.ACC_STATIC) != 0;
}
-
-
- }
- public byte [] transformCode2(byte []b1, String className) throws IOException {
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- InsertMethodBodyAdapter insertMethodBodyAdapter=new InsertMethodBodyAdapter(cw,className,new HashMap());
- ClassReader cr = new ClassReader(b1);
- cr.accept(insertMethodBodyAdapter,ClassReader.EXPAND_FRAMES);
- return cw.toByteArray();
}
- public byte [] transformCode(byte []b1, String className) throws IOException {
+ public byte[] transformCode(byte[] b1, String className) throws IOException {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassReader cr = new ClassReader(b1);
-
ClassNode classNode = new ClassNode();
- Map methodInstructionTypeMap=new HashMap<>();
- cr.accept(classNode,0);
+ Map methodInstructionTypeMap = new HashMap<>();
+ cr.accept(classNode, 0);
final List methods = classNode.methods;
- for(MethodNode m: methods){
+ for (MethodNode m : methods) {
InsnList inList = m.instructions;
- boolean isMethodInvoke=false;
- for(int i = 0; i< inList.size(); i++) {
- if(inList.get(i).getType()==AbstractInsnNode.METHOD_INSN) {
- isMethodInvoke=true;
+ boolean isMethodInvoke = false;
+ for (int i = 0; i < inList.size(); i++) {
+ if (inList.get(i).getType() == AbstractInsnNode.METHOD_INSN) {
+ isMethodInvoke = true;
}
}
methodInstructionTypeMap.put(m.name + m.desc, isMethodInvoke);
}
-// printlnMap(methodInstructionTypeMap);
-
- InsertMethodBodyAdapter insertMethodBodyAdapter=new InsertMethodBodyAdapter(cw,className,methodInstructionTypeMap);
- cr.accept(insertMethodBodyAdapter,ClassReader.EXPAND_FRAMES);
+ InsertMethodBodyAdapter insertMethodBodyAdapter = new InsertMethodBodyAdapter(cw, className, methodInstructionTypeMap);
+ cr.accept(insertMethodBodyAdapter, ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
-
- public static void main(String []args) throws IOException {
-
- AsmInsertImpl asmInsert=new AsmInsertImpl(null,null,null,null,false,false);
-// byte[]bytes= org.apache.commons.io.FileUtils.readFileToByteArray(new File("/Users/zhangmeng/Downloads/asm-5.2/asm/com/meituan/robust/PatchProxy.class"));
-// byte[]bytes= org.apache.commons.io.FileUtils.readFileToByteArray(new File("/Users/zhangmeng/Downloads/asm-5.2/com/meituan/robust/Patch.class"));
- byte[]bytes= org.apache.commons.io.FileUtils.readFileToByteArray(new File("/Users/zhangmeng/Desktop/code/openSource/robust/app/build/intermediates/transforms/aspectJ/release/folders/1/1/main/com/meituan/sample/robusttest/People.class"));
-// org.apache.commons.io.FileUtils.writeByteArrayToFile(new File("/Users/zhangmeng/Downloads/asm-5.2/asm/com/meituan/robust/PatchProxy2.class"),asmInsert.transformCode2(bytes,"com.meituan.robust.PatchProxy","1231"));
-// org.apache.commons.io.FileUtils.writeByteArrayToFile(new File("/Users/zhangmeng/Downloads/asm-5.2/com/meituan/robust/Patch2.class"),asmInsert.transformCode2(bytes,"com.meituan.robust.Patch","1231"));
- org.apache.commons.io.FileUtils.writeByteArrayToFile(new File("/Users/zhangmeng/Desktop/code/openSource/robust/app/build/intermediates/transforms/aspectJ/release/folders/1/1/main/com/meituan/sample/robusttest/People2.class"),asmInsert.transformCode2(bytes,"com.meituan.sample.robusttest.People"));
- }
- private void printlnMap(Map map){
- for (Map.Entry entry : map.entrySet()) {
- System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
-
- }
- }
-
}
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/RobustAsmUtils.java b/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/RobustAsmUtils.java
index b0d9ce5e..427ed253 100644
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/RobustAsmUtils.java
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/asm/RobustAsmUtils.java
@@ -11,398 +11,404 @@
public final class RobustAsmUtils {
- public final static String REDIRECTFIELD_NAME = "changeQuickRedirect";
- public final static String REDIRECTCLASSNAME = Type.getDescriptor(com.meituan.robust.ChangeQuickRedirect.class);
- public final static String PROXYCLASSNAME = "com.meituan.robust.PatchProxy".replace(".", "/");
-
- /**
- * 插入代码
- * @param mv
- * @param className
- * @param args
- * @param returnType
- * @param isStatic
- */
- public static void createInsertCode(GeneratorAdapter mv, String className, List args, Type returnType, boolean isStatic, int methodId){
-
- /**
- * 调用isSupport方法
- */
- prepareMethodParameters(mv,className,args,returnType,isStatic,methodId);
- //开始调用
- mv.visitMethodInsn(Opcodes.INVOKESTATIC,
- PROXYCLASSNAME,
- "isSupport",
- "([Ljava/lang/Object;Ljava/lang/Object;"+REDIRECTCLASSNAME+"ZI[Ljava/lang/Class;Ljava/lang/Class;)Z");
- Label l1 = new Label();
- mv.visitJumpInsn(Opcodes.IFEQ, l1);
- prepareMethodParameters(mv,className,args,returnType,isStatic,methodId);
- //开始调用
- mv.visitMethodInsn(Opcodes.INVOKESTATIC,
- PROXYCLASSNAME,
- "accessDispatch",
- "([Ljava/lang/Object;Ljava/lang/Object;"+REDIRECTCLASSNAME+"ZI[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;");
-
- //判断是否有返回值,代码不同
- if("V".equals(returnType.getDescriptor())){
- mv.visitInsn(Opcodes.POP);
- mv.visitInsn(Opcodes.RETURN);
- }else{
- //强制转化类型
- if(!castPrimateToObj(mv, returnType.getDescriptor())){
- //这里需要注意,如果是数组类型的直接使用即可,如果非数组类型,就得去除前缀了,还有最终是没有结束符;
- //比如:Ljava/lang/String; ==》 java/lang/String
- String newTypeStr = null;
- int len = returnType.getDescriptor().length();
- if(returnType.getDescriptor().startsWith("[")){
- newTypeStr = returnType.getDescriptor().substring(0, len);
- }else{
- newTypeStr = returnType.getDescriptor().substring(1, len-1);
- }
- mv.visitTypeInsn(Opcodes.CHECKCAST, newTypeStr);
- }
-
- //这里还需要做返回类型不同返回指令也不同
- mv.visitInsn(getReturnTypeCode(returnType.getDescriptor()));
- }
-
- mv.visitLabel(l1);
- }
-
- private static void prepareMethodParameters(GeneratorAdapter mv, String className, List args, Type returnType, boolean isStatic, int methodId) {
- //第一个参数:new Object[]{...};,如果方法没有参数直接传入new Object[0]
- if(args.size() == 0){
- mv.visitInsn(Opcodes.ICONST_0);
- mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
- }else{
- createObjectArray(mv, args, isStatic);
- }
-
- //第二个参数:this,如果方法是static的话就直接传入null
- if(isStatic){
- mv.visitInsn(Opcodes.ACONST_NULL);
- }else{
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- }
-
- //第三个参数:changeQuickRedirect
- mv.visitFieldInsn(Opcodes.GETSTATIC,
- className,
- REDIRECTFIELD_NAME,
- REDIRECTCLASSNAME);
-
- //第四个参数:false,标志是否为static
- mv.visitInsn(isStatic ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
- //第五个参数:
- mv.push(methodId);
- //第六个参数:参数class数组
- createClassArray(mv,args);
- //第七个参数:返回值类型class
- createReturnClass(mv,returnType);
- }
-
- private static void createReturnClass(GeneratorAdapter mv, Type returnType) {
- redirectLocal(mv, returnType);
- }
-
- private static void createClassArray(GeneratorAdapter mv, List args){
- // create an array of objects capable of containing all the parameters and optionally the "this"
-
- createLocals(mv, args);
- // we need to maintain the stack index when loading parameters from, as for long and double
- // values, it uses 2 stack elements, all others use only 1 stack element.
- int stackIndex = 0;
- for (int arrayIndex = 0; arrayIndex < args.size(); arrayIndex++) {
- Type arg = args.get(arrayIndex);
- // duplicate the array of objects reference, it will be used to store the value in.
- mv.dup();
- // index in the array of objects to store the boxed parameter.
- mv.push(arrayIndex);
- // Pushes the appropriate local variable on the stack
- redirectLocal(mv, arg);
+ public final static String REDIRECTFIELD_NAME = "changeQuickRedirect";
+ public final static String REDIRECTCLASSNAME = Type.getDescriptor(com.meituan.robust.ChangeQuickRedirect.class);
+ public final static String PROXYCLASSNAME = "com.meituan.robust.PatchProxy".replace(".", "/");
+
+ /**
+ * 插入代码
+ *
+ * @param mv
+ * @param className
+ * @param args
+ * @param returnType
+ * @param isStatic
+ */
+ public static void createInsertCode(GeneratorAdapter mv, String className, List args, Type returnType, boolean isStatic, int methodId) {
+
+ /**
+ * 调用isSupport方法
+ */
+ prepareMethodParameters(mv, className, args, returnType, isStatic, methodId);
+ //开始调用
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC,
+ PROXYCLASSNAME,
+ "isSupport",
+ "([Ljava/lang/Object;Ljava/lang/Object;" + REDIRECTCLASSNAME + "ZI[Ljava/lang/Class;Ljava/lang/Class;)Z");
+ Label l1 = new Label();
+ mv.visitJumpInsn(Opcodes.IFEQ, l1);
+ prepareMethodParameters(mv, className, args, returnType, isStatic, methodId);
+ //开始调用
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC,
+ PROXYCLASSNAME,
+ "accessDispatch",
+ "([Ljava/lang/Object;Ljava/lang/Object;" + REDIRECTCLASSNAME + "ZI[Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;");
+
+ //判断是否有返回值,代码不同
+ if ("V".equals(returnType.getDescriptor())) {
+ mv.visitInsn(Opcodes.POP);
+ mv.visitInsn(Opcodes.RETURN);
+ } else {
+ //强制转化类型
+ if (!castPrimateToObj(mv, returnType.getDescriptor())) {
+ //这里需要注意,如果是数组类型的直接使用即可,如果非数组类型,就得去除前缀了,还有最终是没有结束符;
+ //比如:Ljava/lang/String; ==》 java/lang/String
+ String newTypeStr = null;
+ int len = returnType.getDescriptor().length();
+ if (returnType.getDescriptor().startsWith("[")) {
+ newTypeStr = returnType.getDescriptor().substring(0, len);
+ } else {
+ newTypeStr = returnType.getDescriptor().substring(1, len - 1);
+ }
+ mv.visitTypeInsn(Opcodes.CHECKCAST, newTypeStr);
+ }
+
+ //这里还需要做返回类型不同返回指令也不同
+ mv.visitInsn(getReturnTypeCode(returnType.getDescriptor()));
+ }
+
+ mv.visitLabel(l1);
+ }
+
+ private static void prepareMethodParameters(GeneratorAdapter mv, String className, List args, Type returnType, boolean isStatic, int methodId) {
+ //第一个参数:new Object[]{...};,如果方法没有参数直接传入new Object[0]
+ if (args.size() == 0) {
+ mv.visitInsn(Opcodes.ICONST_0);
+ mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
+ } else {
+ createObjectArray(mv, args, isStatic);
+ }
+
+ //第二个参数:this,如果方法是static的话就直接传入null
+ if (isStatic) {
+ mv.visitInsn(Opcodes.ACONST_NULL);
+ } else {
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ }
+
+ //第三个参数:changeQuickRedirect
+ mv.visitFieldInsn(Opcodes.GETSTATIC,
+ className,
+ REDIRECTFIELD_NAME,
+ REDIRECTCLASSNAME);
+
+ //第四个参数:false,标志是否为static
+ mv.visitInsn(isStatic ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
+ //第五个参数:
+ mv.push(methodId);
+ //第六个参数:参数class数组
+ createClassArray(mv, args);
+ //第七个参数:返回值类型class
+ createReturnClass(mv, returnType);
+ }
+
+ private static void createReturnClass(GeneratorAdapter mv, Type returnType) {
+ redirectLocal(mv, returnType);
+ }
+
+ private static void createClassArray(GeneratorAdapter mv, List args) {
+ // create an array of objects capable of containing all the parameters and optionally the "this"
+
+ createLocals(mv, args);
+ // we need to maintain the stack index when loading parameters from, as for long and double
+ // values, it uses 2 stack elements, all others use only 1 stack element.
+ int stackIndex = 0;
+ for (int arrayIndex = 0; arrayIndex < args.size(); arrayIndex++) {
+ Type arg = args.get(arrayIndex);
+ // duplicate the array of objects reference, it will be used to store the value in.
+ mv.dup();
+ // index in the array of objects to store the boxed parameter.
+ mv.push(arrayIndex);
+ // Pushes the appropriate local variable on the stack
+ redirectLocal(mv, arg);
// mv.visitLdcInsn(Type.getType(arg.getDescriptor()));
- // potentially box up intrinsic types.
+ // potentially box up intrinsic types.
// mv.box(arg);
- mv.arrayStore(Type.getType(Class.class));
- // stack index must progress according to the parameter type we just processed.
+ mv.arrayStore(Type.getType(Class.class));
+ // stack index must progress according to the parameter type we just processed.
// stackIndex += arg.getSize();
- }
- }
-
- /**
- * Creates and pushes to the stack the array to hold all the parameters to redirect, and
- * optionally this.
- */
- protected static void createLocals(GeneratorAdapter mv, List args) {
- mv.push(args.size());
- mv.newArray(Type.getType(Class.class));
- }
- /**
- * Pushes in the stack the value that should be redirected for the given local.
- */
- protected static void redirectLocal(GeneratorAdapter mv, Type arg) {
- switch (arg.getDescriptor()){
- case "Z":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
- break;
- case "B":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
- break;
- case "C":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
- break;
- case "S":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
- break;
- case "I":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
- break;
- case "F":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
- break;
- case "D":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
- break;
- case "J":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
- break;
- case "V":
- mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
- break;
- default:
- mv.visitLdcInsn(Type.getType(arg.getDescriptor()));
- }
-
- }
-
- /**
- * 创建局部参数代码
- * @param mv
- * @param paramsTypeClass
- * @param isStatic
- */
- private static void createObjectArray(MethodVisitor mv, List paramsTypeClass, boolean isStatic){
- //Opcodes.ICONST_0 ~ Opcodes.ICONST_5 这个指令范围
- int argsCount = paramsTypeClass.size();
- //声明 Object[argsCount];
- if(argsCount >= 6){
- mv.visitIntInsn(Opcodes.BIPUSH, argsCount);
- }else{
- mv.visitInsn(Opcodes.ICONST_0+argsCount);
- }
- mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
-
- //如果是static方法,没有this隐含参数
- int loadIndex = (isStatic ? 0 : 1);
-
- //填充数组数据
- for(int i=0;i= 1){
- //这里需要判断当前参数的前面一个参数的类型是什么
- if("J".equals(paramsTypeClass.get(i-1).getDescriptor()) || "D".equals(paramsTypeClass.get(i-1).getDescriptor())){
- //如果前面一个参数是long,double类型,load指令索引就要增加1
- loadIndex ++;
- }
- }
- if(!createPrimateTypeObj(mv, loadIndex, paramsTypeClass.get(i).getDescriptor())){
- mv.visitVarInsn(Opcodes.ALOAD, loadIndex);
- mv.visitInsn(Opcodes.AASTORE);
- }
- loadIndex ++;
- }
- }
-
- private static void createBooleanObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Byte");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Byte", "", "(B)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- private static void createShortObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Short");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Short", "", "(S)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- private static void createCharObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Character");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Character", "", "(C)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- private static void createIntegerObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Integer");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Integer", "", "(I)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- private static void createFloatObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Float");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.FLOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Float", "", "(F)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- private static void createDoubleObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Double");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.DLOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Double", "", "(D)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- private static void createLongObj(MethodVisitor mv, int argsPostion){
- mv.visitTypeInsn(Opcodes.NEW, "java/lang/Long");
- mv.visitInsn(Opcodes.DUP);
- mv.visitVarInsn(Opcodes.LLOAD, argsPostion);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Long", "", "(J)V");
- mv.visitInsn(Opcodes.AASTORE);
- }
-
- /**
- * 创建基本类型对应的对象
- * @param mv
- * @param argsPostion
- * @param typeS
- * @return
- */
- private static boolean createPrimateTypeObj(MethodVisitor mv, int argsPostion, String typeS){
- if("Z".equals(typeS)){
- createBooleanObj(mv, argsPostion);
- return true;
- }
- if("B".equals(typeS)){
- createBooleanObj(mv, argsPostion);
- return true;
- }
- if("C".equals(typeS)){
- createCharObj(mv, argsPostion);
- return true;
- }
- if("S".equals(typeS)){
- createShortObj(mv, argsPostion);
- return true;
- }
- if("I".equals(typeS)){
- createIntegerObj(mv, argsPostion);
- return true;
- }
- if("F".equals(typeS)){
- createFloatObj(mv, argsPostion);
- return true;
- }
- if("D".equals(typeS)){
- createDoubleObj(mv, argsPostion);
- return true;
- }
- if("J".equals(typeS)){
- createLongObj(mv, argsPostion);
- return true;
- }
- return false;
- }
-
- /**
- * 基本类型需要做对象类型分装
- * @param mv
- * @param typeS
- * @return
- */
- private static boolean castPrimateToObj(MethodVisitor mv, String typeS){
- if("Z".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
- return true;
- }
- if("B".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Byte");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
- return true;
- }
- if("C".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Character");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "intValue", "()C");
- return true;
- }
- if("S".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Short");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
- return true;
- }
- if("I".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
- return true;
- }
- if("F".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Float");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
- return true;
- }
- if("D".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Double");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
- return true;
- }
- if("J".equals(typeS)){
- mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Long");//强制转化类型
- mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
- return true;
- }
- return false;
- }
-
- /**
- * 针对不同类型返回指令不一样
- * @param typeS
- * @return
- */
- private static int getReturnTypeCode(String typeS){
- if("Z".equals(typeS)){
- return Opcodes.IRETURN;
- }
- if("B".equals(typeS)){
- return Opcodes.IRETURN;
- }
- if("C".equals(typeS)){
- return Opcodes.IRETURN;
- }
- if("S".equals(typeS)){
- return Opcodes.IRETURN;
- }
- if("I".equals(typeS)){
- return Opcodes.IRETURN;
- }
- if("F".equals(typeS)){
- return Opcodes.FRETURN;
- }
- if("D".equals(typeS)){
- return Opcodes.DRETURN;
- }
- if("J".equals(typeS)){
- return Opcodes.LRETURN;
- }
- return Opcodes.ARETURN;
- }
+ }
+ }
+
+ /**
+ * Creates and pushes to the stack the array to hold all the parameters to redirect, and
+ * optionally this.
+ */
+ protected static void createLocals(GeneratorAdapter mv, List args) {
+ mv.push(args.size());
+ mv.newArray(Type.getType(Class.class));
+ }
+
+ /**
+ * Pushes in the stack the value that should be redirected for the given local.
+ */
+ protected static void redirectLocal(GeneratorAdapter mv, Type arg) {
+ switch (arg.getDescriptor()) {
+ case "Z":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "B":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "C":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "S":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "I":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "F":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "D":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "J":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
+ break;
+ case "V":
+ mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
+ break;
+ default:
+ mv.visitLdcInsn(Type.getType(arg.getDescriptor()));
+ }
+
+ }
+
+ /**
+ * 创建局部参数代码
+ *
+ * @param mv
+ * @param paramsTypeClass
+ * @param isStatic
+ */
+ private static void createObjectArray(MethodVisitor mv, List paramsTypeClass, boolean isStatic) {
+ //Opcodes.ICONST_0 ~ Opcodes.ICONST_5 这个指令范围
+ int argsCount = paramsTypeClass.size();
+ //声明 Object[argsCount];
+ if (argsCount >= 6) {
+ mv.visitIntInsn(Opcodes.BIPUSH, argsCount);
+ } else {
+ mv.visitInsn(Opcodes.ICONST_0 + argsCount);
+ }
+ mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
+
+ //如果是static方法,没有this隐含参数
+ int loadIndex = (isStatic ? 0 : 1);
+
+ //填充数组数据
+ for (int i = 0; i < argsCount; i++) {
+ mv.visitInsn(Opcodes.DUP);
+ if (i <= 5) {
+ mv.visitInsn(Opcodes.ICONST_0 + i);
+ } else {
+ mv.visitIntInsn(Opcodes.BIPUSH, i);
+ }
+
+ //这里又要做特殊处理,在实践过程中发现个问题:public void xxx(long a, boolean b, double c,int d)
+ //当一个参数的前面一个参数是long或者是double类型的话,后面参数在使用LOAD指令,加载数据索引值要+1
+ //个人猜想是和long,double是8个字节的问题有关系。这里做了处理
+ //比如这里的参数:[a=LLOAD 1] [b=ILOAD 3] [c=DLOAD 4] [d=ILOAD 6];
+ if (i >= 1) {
+ //这里需要判断当前参数的前面一个参数的类型是什么
+ if ("J".equals(paramsTypeClass.get(i - 1).getDescriptor()) || "D".equals(paramsTypeClass.get(i - 1).getDescriptor())) {
+ //如果前面一个参数是long,double类型,load指令索引就要增加1
+ loadIndex++;
+ }
+ }
+ if (!createPrimateTypeObj(mv, loadIndex, paramsTypeClass.get(i).getDescriptor())) {
+ mv.visitVarInsn(Opcodes.ALOAD, loadIndex);
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+ loadIndex++;
+ }
+ }
+
+ private static void createBooleanObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Byte");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Byte", "", "(B)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ private static void createShortObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Short");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Short", "", "(S)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ private static void createCharObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Character");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Character", "", "(C)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ private static void createIntegerObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Integer");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.ILOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Integer", "", "(I)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ private static void createFloatObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Float");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.FLOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Float", "", "(F)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ private static void createDoubleObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Double");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.DLOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Double", "", "(D)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ private static void createLongObj(MethodVisitor mv, int argsPostion) {
+ mv.visitTypeInsn(Opcodes.NEW, "java/lang/Long");
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitVarInsn(Opcodes.LLOAD, argsPostion);
+ mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Long", "", "(J)V");
+ mv.visitInsn(Opcodes.AASTORE);
+ }
+
+ /**
+ * 创建基本类型对应的对象
+ *
+ * @param mv
+ * @param argsPostion
+ * @param typeS
+ * @return
+ */
+ private static boolean createPrimateTypeObj(MethodVisitor mv, int argsPostion, String typeS) {
+ if ("Z".equals(typeS)) {
+ createBooleanObj(mv, argsPostion);
+ return true;
+ }
+ if ("B".equals(typeS)) {
+ createBooleanObj(mv, argsPostion);
+ return true;
+ }
+ if ("C".equals(typeS)) {
+ createCharObj(mv, argsPostion);
+ return true;
+ }
+ if ("S".equals(typeS)) {
+ createShortObj(mv, argsPostion);
+ return true;
+ }
+ if ("I".equals(typeS)) {
+ createIntegerObj(mv, argsPostion);
+ return true;
+ }
+ if ("F".equals(typeS)) {
+ createFloatObj(mv, argsPostion);
+ return true;
+ }
+ if ("D".equals(typeS)) {
+ createDoubleObj(mv, argsPostion);
+ return true;
+ }
+ if ("J".equals(typeS)) {
+ createLongObj(mv, argsPostion);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 基本类型需要做对象类型分装
+ *
+ * @param mv
+ * @param typeS
+ * @return
+ */
+ private static boolean castPrimateToObj(MethodVisitor mv, String typeS) {
+ if ("Z".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Boolean");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
+ return true;
+ }
+ if ("B".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Byte");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B");
+ return true;
+ }
+ if ("C".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Character");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "intValue", "()C");
+ return true;
+ }
+ if ("S".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Short");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S");
+ return true;
+ }
+ if ("I".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Integer");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I");
+ return true;
+ }
+ if ("F".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Float");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F");
+ return true;
+ }
+ if ("D".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Double");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D");
+ return true;
+ }
+ if ("J".equals(typeS)) {
+ mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Long");//强制转化类型
+ mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 针对不同类型返回指令不一样
+ *
+ * @param typeS
+ * @return
+ */
+ private static int getReturnTypeCode(String typeS) {
+ if ("Z".equals(typeS)) {
+ return Opcodes.IRETURN;
+ }
+ if ("B".equals(typeS)) {
+ return Opcodes.IRETURN;
+ }
+ if ("C".equals(typeS)) {
+ return Opcodes.IRETURN;
+ }
+ if ("S".equals(typeS)) {
+ return Opcodes.IRETURN;
+ }
+ if ("I".equals(typeS)) {
+ return Opcodes.IRETURN;
+ }
+ if ("F".equals(typeS)) {
+ return Opcodes.FRETURN;
+ }
+ if ("D".equals(typeS)) {
+ return Opcodes.DRETURN;
+ }
+ if ("J".equals(typeS)) {
+ return Opcodes.LRETURN;
+ }
+ return Opcodes.ARETURN;
+ }
}
\ No newline at end of file
diff --git a/gradle-plugin/src/main/groovy/robust/gradle/plugin/javaassist/JavaAssistInsertImpl.java b/gradle-plugin/src/main/groovy/robust/gradle/plugin/javaassist/JavaAssistInsertImpl.java
index 8e03769d..a077fd04 100644
--- a/gradle-plugin/src/main/groovy/robust/gradle/plugin/javaassist/JavaAssistInsertImpl.java
+++ b/gradle-plugin/src/main/groovy/robust/gradle/plugin/javaassist/JavaAssistInsertImpl.java
@@ -30,6 +30,7 @@
/**
* Created by zhangmeng on 2017/5/10.
+ * this class do almost the same thing with AsmInsertImpl
*/
public class JavaAssistInsertImpl extends InsertcodeStrategy {
@@ -40,57 +41,64 @@ public JavaAssistInsertImpl(List hotfixPackageList, List hotfixM
@Override
protected void insertCode(List box, File jarFile) throws CannotCompileException, IOException, NotFoundException {
- ZipOutputStream outStream=new JarOutputStream(new FileOutputStream(jarFile));
+ ZipOutputStream outStream = new JarOutputStream(new FileOutputStream(jarFile));
// new ForkJoinPool().submit {
- for(CtClass ctClass:box) {
- if (isNeedInsertClass(ctClass.getName())) {
- ctClass.setModifiers(AccessFlag.setPublic(ctClass.getModifiers()));
- if (ctClass.isInterface() || ctClass.getDeclaredMethods().length < 1) {
- zipFile(ctClass.toBytecode(), outStream, ctClass.getName().replaceAll("\\.", "/") + ".class");
+ for (CtClass ctClass : box) {
+ if (isNeedInsertClass(ctClass.getName())) {
+ //change class modifier
+ ctClass.setModifiers(AccessFlag.setPublic(ctClass.getModifiers()));
+ if (ctClass.isInterface() || ctClass.getDeclaredMethods().length < 1) {
+ //skip the unsatisfied class
+ zipFile(ctClass.toBytecode(), outStream, ctClass.getName().replaceAll("\\.", "/") + ".class");
+ continue;
+ }
+
+ boolean addIncrementalChange = false;
+ for (CtBehavior ctBehavior : ctClass.getDeclaredBehaviors()) {
+ if (!addIncrementalChange) {
+ //insert the field
+ addIncrementalChange = true;
+ ClassPool classPool = ctBehavior.getDeclaringClass().getClassPool();
+ CtClass type = classPool.getOrNull(Constants.INTERFACE_NAME);
+ CtField ctField = new CtField(type, Constants.INSERT_FIELD_NAME, ctClass);
+ ctField.setModifiers(AccessFlag.PUBLIC | AccessFlag.STATIC);
+ ctClass.addField(ctField);
+ }
+ if (!isQualifiedMethod(ctBehavior)) {
continue;
}
-
- boolean addIncrementalChange = false;
- for (CtBehavior ctBehavior : ctClass.getDeclaredBehaviors()) {
- if (!addIncrementalChange) {
- addIncrementalChange = true;
- ClassPool classPool = ctBehavior.getDeclaringClass().getClassPool();
- CtClass type = classPool.getOrNull(Constants.INTERFACE_NAME);
- CtField ctField = new CtField(type, Constants.INSERT_FIELD_NAME, ctClass);
- ctField.setModifiers(AccessFlag.PUBLIC | AccessFlag.STATIC);
- ctClass.addField(ctField);
- }
- if(!isQualifiedMethod(ctBehavior)){
- continue;
- }
- //here comes the method will be inserted code
- methodMap.put(ctBehavior.getLongName(), insertMethodCount.incrementAndGet());
- try {
- if (ctBehavior.getMethodInfo().isMethod()) {
- CtMethod ctMethod=(CtMethod)ctBehavior;
- boolean isStatic = (ctMethod.getModifiers() & AccessFlag.STATIC)!= 0;
- CtClass returnType = ctMethod.getReturnType();
- String returnTypeString = returnType.getName();
- String body = "Object argThis = null;";
- if (!isStatic) {
- body += "argThis = $0;";
- }
- String parametersClassType=getParametersClassType(ctMethod);
-// body += " if (com.meituan.robust.PatchProxy.isSupport(\$args, argThis, ${Constants.INSERT_FIELD_NAME}, $isStatic, " + methodMap.get(ctBehavior.longName) + ",${parametersClassType},${returnTypeString}.class)) {"
- body += " if (com.meituan.robust.PatchProxy.isSupport($args, argThis, "+Constants.INSERT_FIELD_NAME+", "+isStatic+
- ", " + methodMap.get(ctBehavior.getLongName()) + ","+parametersClassType+","+returnTypeString+".class)) {";
- body += getReturnStatement(returnTypeString, isStatic, methodMap.get(ctBehavior.getLongName()),parametersClassType,returnTypeString+".class");
- body += " }";
- ctBehavior.insertBefore(body);
+ //here comes the method will be inserted code
+ methodMap.put(ctBehavior.getLongName(), insertMethodCount.incrementAndGet());
+ try {
+ if (ctBehavior.getMethodInfo().isMethod()) {
+ CtMethod ctMethod = (CtMethod) ctBehavior;
+ boolean isStatic = (ctMethod.getModifiers() & AccessFlag.STATIC) != 0;
+ CtClass returnType = ctMethod.getReturnType();
+ String returnTypeString = returnType.getName();
+ //construct the code will be inserted in string format
+ String body = "Object argThis = null;";
+ if (!isStatic) {
+ body += "argThis = $0;";
}
- } catch (Throwable t ) {
- t.printStackTrace();
- System.out.println("ctClass: " + ctClass.getName() + " error: " + t.getMessage());
+ String parametersClassType = getParametersClassType(ctMethod);
+// body += " if (com.meituan.robust.PatchProxy.isSupport(\$args, argThis, ${Constants.INSERT_FIELD_NAME}, $isStatic, " + methodMap.get(ctBehavior.longName) + ",${parametersClassType},${returnTypeString}.class)) {"
+ body += " if (com.meituan.robust.PatchProxy.isSupport($args, argThis, " + Constants.INSERT_FIELD_NAME + ", " + isStatic +
+ ", " + methodMap.get(ctBehavior.getLongName()) + "," + parametersClassType + "," + returnTypeString + ".class)) {";
+ body += getReturnStatement(returnTypeString, isStatic, methodMap.get(ctBehavior.getLongName()), parametersClassType, returnTypeString + ".class");
+ body += " }";
+ //finish the insert-code body ,let`s insert it
+ ctBehavior.insertBefore(body);
}
+ } catch (Throwable t) {
+ //here we ignore the error
+ t.printStackTrace();
+ System.out.println("ctClass: " + ctClass.getName() + " error: " + t.getMessage());
}
}
- zipFile(ctClass.toBytecode(), outStream, ctClass.getName().replaceAll("\\.", "/") + ".class");
}
+ //zip the inserted-classes into output file
+ zipFile(ctClass.toBytecode(), outStream, ctClass.getName().replaceAll("\\.", "/") + ".class");
+ }
// }.get()
outStream.close();
}
@@ -146,25 +154,28 @@ private boolean isQualifiedMethod(CtBehavior it) throws CannotCompileException {
return !isHotfixMethodLevel;
}
- private String getParametersClassType(CtMethod method) throws NotFoundException {
- if(method.getParameterTypes().length==0){
+ private String getParametersClassType(CtMethod method) throws NotFoundException {
+ if (method.getParameterTypes().length == 0) {
return " null ";
}
- StringBuilder parameterType=new StringBuilder();
+ StringBuilder parameterType = new StringBuilder();
parameterType.append("new Class[]{");
- for(CtClass paramterClass:method.getParameterTypes()){
+ for (CtClass paramterClass : method.getParameterTypes()) {
parameterType.append(paramterClass.getName()).append(".class,");
}
//remove last ','
- if(','==parameterType.charAt(parameterType.length()-1))
- parameterType.deleteCharAt(parameterType.length()-1);
+ if (',' == parameterType.charAt(parameterType.length() - 1))
+ parameterType.deleteCharAt(parameterType.length() - 1);
parameterType.append("}");
return parameterType.toString();
}
+
//判断代码中是否有方法调用
private boolean isCallMethod = false;
+
/**
* 判断是否有方法调用
+ *
* @return 是否插桩
*/
private boolean isMethodWithExpression(CtMethod ctMethod) throws CannotCompileException {
@@ -189,14 +200,18 @@ private boolean isMethodWithExpression(CtMethod ctMethod) throws CannotCompileEx
* @param a the new expression for creating an array.
* @throws CannotCompileException
*/
- public void edit(NewArray a) throws CannotCompileException { isCallMethod = true; }
+ public void edit(NewArray a) throws CannotCompileException {
+ isCallMethod = true;
+ }
/**
* Edits a method call (overridable).
*
* The default implementation performs nothing.
*/
- public void edit(MethodCall m) throws CannotCompileException { isCallMethod = true; }
+ public void edit(MethodCall m) throws CannotCompileException {
+ isCallMethod = true;
+ }
/**
* Edits a constructor call (overridable).
@@ -216,79 +231,87 @@ public void edit(ConstructorCall c) throws CannotCompileException {
* Edits an instanceof expression (overridable).
* The default implementation performs nothing.
*/
- public void edit(Instanceof i) throws CannotCompileException { isCallMethod = true; }
+ public void edit(Instanceof i) throws CannotCompileException {
+ isCallMethod = true;
+ }
/**
* Edits an expression for explicit type casting (overridable).
* The default implementation performs nothing.
*/
- public void edit(Cast c) throws CannotCompileException { isCallMethod = true; }
+ public void edit(Cast c) throws CannotCompileException {
+ isCallMethod = true;
+ }
/**
* Edits a catch clause (overridable).
* The default implementation performs nothing.
*/
- public void edit(Handler h) throws CannotCompileException { isCallMethod = true; }
+ public void edit(Handler h) throws CannotCompileException {
+ isCallMethod = true;
+ }
});
return isCallMethod;
}
+
/**
* 根据传入类型判断调用PathProxy的方法
- * @param type 返回类型
- * @param isStatic 是否是静态方法
+ *
+ * @param type 返回类型
+ * @param isStatic 是否是静态方法
* @param methodNumber 方法数
* @return 返回return语句
*/
- private String getReturnStatement(String type, boolean isStatic, int methodNumber,String parametersClassType,String returnTypeString) {
+ private String getReturnStatement(String type, boolean isStatic, int methodNumber, String parametersClassType, String returnTypeString) {
switch (type) {
case Constants.CONSTRUCTOR:
- return " com.meituan.robust.PatchProxy.accessDispatchVoid( $args, argThis, changeQuickRedirect, "+isStatic+", "+methodNumber+","+parametersClassType+","+returnTypeString+"); ";
+ return " com.meituan.robust.PatchProxy.accessDispatchVoid( $args, argThis, changeQuickRedirect, " + isStatic + ", " + methodNumber + "," + parametersClassType + "," + returnTypeString + "); ";
case Constants.LANG_VOID:
- return " com.meituan.robust.PatchProxy.accessDispatchVoid( $args, argThis, changeQuickRedirect, "+isStatic+", "+methodNumber+","+parametersClassType+","+returnTypeString+"); return null;";
+ return " com.meituan.robust.PatchProxy.accessDispatchVoid( $args, argThis, changeQuickRedirect, " + isStatic + ", " + methodNumber + "," + parametersClassType + "," + returnTypeString + "); return null;";
case Constants.VOID:
- return " com.meituan.robust.PatchProxy.accessDispatchVoid( $args, argThis, changeQuickRedirect, "+isStatic+", "+methodNumber+","+parametersClassType+","+returnTypeString+"); return ;";
+ return " com.meituan.robust.PatchProxy.accessDispatchVoid( $args, argThis, changeQuickRedirect, " + isStatic + ", " + methodNumber + "," + parametersClassType + "," + returnTypeString + "); return ;";
case Constants.LANG_BOOLEAN:
- return " return ((java.lang.Boolean)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Boolean)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
case Constants.BOOLEAN:
- return " return ((java.lang.Boolean)com.meituan.robust.PatchProxy.accessDispatch($args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).booleanValue();";
+ return " return ((java.lang.Boolean)com.meituan.robust.PatchProxy.accessDispatch($args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).booleanValue();";
case Constants.INT:
- return " return ((java.lang.Integer)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).intValue();";
+ return " return ((java.lang.Integer)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).intValue();";
case Constants.LANG_INT:
- return " return ((java.lang.Integer)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+methodNumber+","+parametersClassType+","+returnTypeString+")); ";
+ return " return ((java.lang.Integer)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")); ";
case Constants.LONG:
- return " return ((java.lang.Long)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).longValue();";
+ return " return ((java.lang.Long)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).longValue();";
case Constants.LANG_LONG:
- return " return ((java.lang.Long)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Long)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
case Constants.DOUBLE:
- return " return ((java.lang.Double)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).doubleValue();";
+ return " return ((java.lang.Double)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).doubleValue();";
case Constants.LANG_DOUBLE:
- return " return ((java.lang.Double)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Double)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
case Constants.FLOAT:
- return " return ((java.lang.Float)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).floatValue();";
+ return " return ((java.lang.Float)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).floatValue();";
case Constants.LANG_FLOAT:
- return " return ((java.lang.Float)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Float)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
case Constants.SHORT:
- return " return ((java.lang.Short)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).shortValue();";
+ return " return ((java.lang.Short)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).shortValue();";
case Constants.LANG_SHORT:
- return " return ((java.lang.Short)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Short)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
case Constants.BYTE:
- return " return ((java.lang.Byte)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).byteValue();";
+ return " return ((java.lang.Byte)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).byteValue();";
case Constants.LANG_BYTE:
- return " return ((java.lang.Byte)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Byte)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
case Constants.CHAR:
- return " return ((java.lang.Character)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+")).charValue();";
+ return " return ((java.lang.Character)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ")).charValue();";
case Constants.LANG_CHARACTER:
- return " return ((java.lang.Character)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+"));";
+ return " return ((java.lang.Character)com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + "));";
default:
- return " return ("+type+")com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, "+isStatic+","+ methodNumber+","+parametersClassType+","+returnTypeString+");";
+ return " return (" + type + ")com.meituan.robust.PatchProxy.accessDispatch( $args, argThis, changeQuickRedirect, " + isStatic + "," + methodNumber + "," + parametersClassType + "," + returnTypeString + ");";
}
}
}
diff --git "a/images/Robust\347\273\223\346\236\204\345\233\276.png" "b/images/Robust\347\273\223\346\236\204\345\233\276.png"
new file mode 100644
index 00000000..35d8ab10
Binary files /dev/null and "b/images/Robust\347\273\223\346\236\204\345\233\276.png" differ
diff --git "a/images/\350\241\245\344\270\201\344\273\243\347\240\201\347\273\223\346\236\204.png" "b/images/\350\241\245\344\270\201\344\273\243\347\240\201\347\273\223\346\236\204.png"
new file mode 100644
index 00000000..e3aafcb9
Binary files /dev/null and "b/images/\350\241\245\344\270\201\344\273\243\347\240\201\347\273\223\346\236\204.png" differ
diff --git a/patch/src/main/java/com/meituan/robust/PatchedClassInfo.java b/patch/src/main/java/com/meituan/robust/PatchedClassInfo.java
index cf73c488..40e628c3 100644
--- a/patch/src/main/java/com/meituan/robust/PatchedClassInfo.java
+++ b/patch/src/main/java/com/meituan/robust/PatchedClassInfo.java
@@ -2,6 +2,7 @@
/**
* Created by hedex on 16/6/3.
+ * a map record the class name before ProGuard and after ProGuard
*/
public class PatchedClassInfo {
public String patchedClassName;
diff --git a/patch/src/main/java/com/meituan/robust/PatchesInfo.java b/patch/src/main/java/com/meituan/robust/PatchesInfo.java
index 80b9aa72..c2f9f950 100644
--- a/patch/src/main/java/com/meituan/robust/PatchesInfo.java
+++ b/patch/src/main/java/com/meituan/robust/PatchesInfo.java
@@ -4,6 +4,7 @@
/**
* Created by c_kunwu on 16/5/12.
+ * an interface describe patch.jar info
*/
public interface PatchesInfo {
List getPatchedClassesInfo();