├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── themes.xml │ │ ├── raw │ │ │ ├── ic_bg.png │ │ │ └── ic_func.jpg │ │ ├── drawable │ │ │ ├── ic_launcher.png │ │ │ └── ic_baseline_delete_outline_24.xml │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.jpeg │ │ ├── values-night │ │ │ └── themes.xml │ │ └── layout │ │ │ ├── layout_view.xml │ │ │ ├── activity_home_page.xml │ │ │ ├── layout_data.xml │ │ │ └── layout_func.xml │ │ ├── java │ │ └── com │ │ │ └── ng │ │ │ └── xerath │ │ │ ├── ui │ │ │ ├── view │ │ │ │ ├── temp.java │ │ │ │ └── rounded │ │ │ │ │ ├── Corner.java │ │ │ │ │ └── RoundedFrameLayout.java │ │ │ ├── adapter │ │ │ │ ├── ItemInfo.java │ │ │ │ └── MyViewPagerAdapter.java │ │ │ ├── fragment │ │ │ │ ├── BaseFragment.kt │ │ │ │ ├── FunctionFragment.java │ │ │ │ └── DataFragment.java │ │ │ └── HomePageActivity.java │ │ │ ├── func │ │ │ ├── chain │ │ │ │ ├── ChainC.java │ │ │ │ ├── ChainB.java │ │ │ │ ├── ChainA.java │ │ │ │ └── ChainD.java │ │ │ ├── ViewMethodUtil.java │ │ │ ├── member │ │ │ │ └── TestMember1.java │ │ │ ├── FuncMethodUtil.java │ │ │ └── DataMethodUtil.java │ │ │ ├── MyApp.java │ │ │ └── asm │ │ │ ├── Parameter.java │ │ │ ├── visitor │ │ │ ├── TestClassVisitor.java │ │ │ ├── TestPreLoadClassVisitor.java │ │ │ ├── TestPreLoadAdviceAdapter.java │ │ │ └── TestAdviceAdapter.java │ │ │ ├── ASMShow.java │ │ │ ├── Main.java │ │ │ ├── ASMUtil.java │ │ │ └── Utils.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro ├── plugin-rule.gradle └── build.gradle ├── README.zh-CN.md ├── XerathCore ├── .gitignore ├── consumer-rules.pro ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── ng │ │ └── xerathcore │ │ ├── utils │ │ ├── LogUtil.java │ │ ├── CoreUtils.java │ │ ├── JsonPrinter.java │ │ ├── ThreadUtil.java │ │ ├── LineNumberLog.java │ │ ├── ResultPrinter.java │ │ └── ParameterPrinter.java │ │ ├── constants │ │ └── PlugConstant.java │ │ ├── annotation │ │ ├── Xerath_CallChain.java │ │ ├── Xerath_TryCatch.java │ │ ├── Xerath_CalculateTime.java │ │ ├── Xerath_CollectParams.java │ │ ├── Xerath_LimitCall.java │ │ ├── Xerath_PopToast.java │ │ ├── Xerath_MethodRemove.java │ │ ├── Xerath_MethodCompleteRemove.java │ │ └── Xerath_MethodReplace.java │ │ ├── func │ │ └── TrackMethodStackHelper.java │ │ ├── XerathEngine.java │ │ ├── bean │ │ └── ObjectNode.java │ │ └── CoreHelper.java ├── proguard-rules.pro └── build.gradle ├── XerathLib ├── .gitignore ├── consumer-rules.pro ├── src │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── gradle-plugins │ │ │ │ └── ng-xerath-plugin.properties │ │ ├── java │ │ │ └── com │ │ │ │ └── ng │ │ │ │ └── xerathlib │ │ │ │ ├── utils │ │ │ │ ├── Pair.java │ │ │ │ ├── LogUtil.java │ │ │ │ ├── Parameter.java │ │ │ │ ├── ASMUtil.java │ │ │ │ └── TxtUtils.java │ │ │ │ ├── extension │ │ │ │ ├── ExtConstant.java │ │ │ │ └── bean │ │ │ │ │ ├── TransformExt.java │ │ │ │ │ └── TrackMethodStack.java │ │ │ │ ├── hook │ │ │ │ ├── target │ │ │ │ │ ├── base │ │ │ │ │ │ ├── ITargetPlug.java │ │ │ │ │ │ └── TargetPlug.java │ │ │ │ │ ├── plug │ │ │ │ │ │ ├── TrackMethodStackPlug.java │ │ │ │ │ │ ├── TargetPlugCreator.java │ │ │ │ │ │ └── TargetPlugFilter.java │ │ │ │ │ └── TargetHookHelper.java │ │ │ │ ├── annotation │ │ │ │ │ ├── plug │ │ │ │ │ │ ├── base │ │ │ │ │ │ │ ├── IAnnotationPlug.java │ │ │ │ │ │ │ ├── AnnotationPlug.java │ │ │ │ │ │ │ └── AnnotationPlugCreator.java │ │ │ │ │ │ ├── PopToastPlug.java │ │ │ │ │ │ ├── CallChainPlug.java │ │ │ │ │ │ ├── LimitCallPlug.java │ │ │ │ │ │ ├── MethodRemovePlug.java │ │ │ │ │ │ ├── CalculateTimePlug.java │ │ │ │ │ │ ├── TryCatchPlug.java │ │ │ │ │ │ └── MethodReplacePlug.java │ │ │ │ │ └── AnnotationHookHelper.java │ │ │ │ ├── HookLifeCycle.java │ │ │ │ ├── XerathHookManager.java │ │ │ │ ├── params │ │ │ │ │ └── HookParams.java │ │ │ │ └── XerathHookHelper.java │ │ │ │ └── asm │ │ │ │ ├── tree │ │ │ │ └── TreeClassVisitor.java │ │ │ │ ├── jar │ │ │ │ ├── JarHookMethodVisitor.java │ │ │ │ ├── JarClassVisitor.java │ │ │ │ └── JarCatchMethodVisitor.java │ │ │ │ ├── preload │ │ │ │ ├── PreLoadClassVisitor.java │ │ │ │ └── PreLoadMethodAdapter.java │ │ │ │ ├── base │ │ │ │ └── BaseClassVisitor.java │ │ │ │ ├── core │ │ │ │ └── CoreClassVisitor.java │ │ │ │ └── HookClassExecutor.java │ │ └── groovy │ │ │ └── com │ │ │ └── ng │ │ │ └── xerathlib │ │ │ ├── transform │ │ │ ├── util │ │ │ │ ├── PkgUtils.java │ │ │ │ ├── TransformUtil.groovy │ │ │ │ └── ClassLoaderHelper.java │ │ │ └── executer │ │ │ │ └── AppTransformExecutor.groovy │ │ │ └── XerathTransformPlugin.groovy │ └── androidTest │ │ └── java │ │ └── com │ │ └── ng │ │ └── xerathlib │ │ └── ExampleInstrumentedTest.java ├── build.gradle └── proguard-rules.pro ├── repo ├── ivy-1.0.0.xml.sha1 ├── XerathLib-1.0.0.jar.sha1 ├── com │ └── ng │ │ └── xerathlib │ │ └── XerathCore │ │ ├── maven-metadata.xml.md5 │ │ ├── 1.0.1 │ │ ├── XerathCore-1.0.1.aar.md5 │ │ ├── XerathCore-1.0.1.pom.md5 │ │ ├── XerathCore-1.0.1.aar.sha1 │ │ ├── XerathCore-1.0.1.pom.sha1 │ │ ├── XerathCore-1.0.1.aar │ │ └── XerathCore-1.0.1.pom │ │ ├── maven-metadata.xml.sha1 │ │ └── maven-metadata.xml ├── ivy-1.0.0.xml.sha256 ├── XerathLib-1.0.0.jar.sha256 ├── XerathLib-1.0.0.jar ├── ivy-1.0.0.xml.sha512 ├── XerathLib-1.0.0.jar.sha512 └── ivy-1.0.0.xml ├── .idea ├── .gitignore ├── vcs.xml ├── compiler.xml ├── deploymentTargetDropDown.xml ├── misc.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml └── jarRepositories.xml ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── upload.sh ├── .gitignore ├── MyTask ├── gradle.properties ├── gradlew.bat └── README.md /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | ewqewq 2 | -------------------------------------------------------------------------------- /XerathCore/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /XerathLib/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /XerathLib/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /XerathCore/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /repo/ivy-1.0.0.xml.sha1: -------------------------------------------------------------------------------- 1 | daf42f337ec48966f3b09da318423d14ad8bfccb -------------------------------------------------------------------------------- /repo/XerathLib-1.0.0.jar.sha1: -------------------------------------------------------------------------------- 1 | a227a57716cd296a901c451971cd0410c6d18986 -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/maven-metadata.xml.md5: -------------------------------------------------------------------------------- 1 | 28d3899bc9ad38a38c1189a8eb171930 -------------------------------------------------------------------------------- /repo/ivy-1.0.0.xml.sha256: -------------------------------------------------------------------------------- 1 | ac20203524f5ed221b0904b480dc2dfd1feb173b0954f6e74e6bfafdbda6ffa5 -------------------------------------------------------------------------------- /repo/XerathLib-1.0.0.jar.sha256: -------------------------------------------------------------------------------- 1 | 77afde08848194a07ff32b40043ddfa4a08b460f18d7a1c8901b4baf78e43806 -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.aar.md5: -------------------------------------------------------------------------------- 1 | 3d3eac4a1a0f39ce701aff69f35cfb33 -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.pom.md5: -------------------------------------------------------------------------------- 1 | 7bde78f678ef952c8b473469778e8f86 -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/maven-metadata.xml.sha1: -------------------------------------------------------------------------------- 1 | 078078fee091e6db222b7f10cb4d451b9a5d21e7 -------------------------------------------------------------------------------- /repo/XerathLib-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/repo/XerathLib-1.0.0.jar -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.aar.sha1: -------------------------------------------------------------------------------- 1 | 0448a4e6fe9a626a4504c80375bcd83a03a5c765 -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.pom.sha1: -------------------------------------------------------------------------------- 1 | 4a58aeaa161a680e3e710b8bd55eb4165c710bc7 -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Xerath 3 | -------------------------------------------------------------------------------- /app/src/main/res/raw/ic_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/app/src/main/res/raw/ic_bg.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "Xerath" 2 | include ':app' 3 | include ':XerathLib' 4 | include ':XerathCore' 5 | -------------------------------------------------------------------------------- /app/src/main/res/raw/ic_func.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/app/src/main/res/raw/ic_func.jpg -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/app/src/main/res/drawable/ic_launcher.png -------------------------------------------------------------------------------- /XerathLib/src/main/resources/META-INF/gradle-plugins/ng-xerath-plugin.properties: -------------------------------------------------------------------------------- 1 | implementation-class = com.ng.xerathlib.XerathTransformPlugin -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.jpeg -------------------------------------------------------------------------------- /repo/ivy-1.0.0.xml.sha512: -------------------------------------------------------------------------------- 1 | a3b2edefab707d0b84ffb497da1dec66bfc5730dfacab7167e3452644ac12ef178e1fd326a6cd7f756ef87ff8d61780f26c95b50d71fb6d94611e7f442589742 -------------------------------------------------------------------------------- /repo/XerathLib-1.0.0.jar.sha512: -------------------------------------------------------------------------------- 1 | de74499402601df93c92dc40757d58d37ac1c03b4f2fd43e0b41733b125a906b06302a14fab117fa663b16164bfe174b6db032d52bf66a05468f4688ce9987b4 -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jiangzhengnan/Xerath/HEAD/repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.aar -------------------------------------------------------------------------------- /XerathCore/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/ui/view/temp.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.ui.view; 2 | 3 | /** 4 | * @author : jiangzhengnan.jzn@alibaba-inc.com 5 | * @creation : 2022/03/10 6 | * @description : 7 | */ 8 | public class temp { 9 | } 10 | -------------------------------------------------------------------------------- /upload.sh: -------------------------------------------------------------------------------- 1 | ./gradlew clean 2 | # 发布核心组件 3 | ./gradlew :XerathLib:uploadArchives 4 | # 编译 5 | ./gradlew :app:assembleDebug 6 | # 安装 7 | ./gradlew :app:installDebug 8 | # 推到手机 9 | adb shell am start -n com.ng.xerath/com.ng.xerath.MainActivity 10 | 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Aug 30 13:53:26 CST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/func/chain/ChainC.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.func.chain; 2 | 3 | /** 4 | * @author : jiangzhengnan.jzn 5 | * @creation : 2021/09/25 6 | * @description : 7 | */ 8 | public class ChainC { 9 | public String c_params = "c_params"; 10 | 11 | public ChainD child; 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/func/chain/ChainB.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.func.chain; 2 | 3 | /** 4 | * @author : jiangzhengnan.jzn 5 | * @creation : 2021/09/25 6 | * @description : 7 | */ 8 | public class ChainB extends ChainA{ 9 | public String b_params = "b_params"; 10 | 11 | public ChainC child; 12 | } 13 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/utils/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.utils; 2 | 3 | /** 4 | * 描述: 5 | * 6 | * @author Jzn 7 | * @date 2021/9/4 8 | */ 9 | public class LogUtil { 10 | private static final String TAG = "Xerath"; 11 | 12 | public static void print(String s) { 13 | System.out.println("[ " + TAG + " ] " + s); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/constants/PlugConstant.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.constants; 2 | 3 | /** 4 | * @author : jiangzhengnan.jzn 5 | * @creation : 2021/09/20 6 | * @description : 7 | */ 8 | public class PlugConstant { 9 | 10 | public static final class SpName { 11 | public final static String LIMIT_CALL_TIME = "limit_call_time"; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/utils/Pair.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.utils; 2 | 3 | /** 4 | * 描述: 5 | * 6 | * @author Jzn 7 | * @date 2021/9/23 8 | */ 9 | public class Pair { 10 | 11 | public Integer key; 12 | public Integer value; 13 | 14 | public Pair(Integer key, Integer value) { 15 | this.key = key; 16 | this.value = value; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/maven-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.ng.xerathlib 4 | XerathCore 5 | 6 | 1.0.0 7 | 8 | 1.0.1 9 | 1.0.0 10 | 11 | 20220602063645 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_delete_outline_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/func/ViewMethodUtil.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.func; 2 | 3 | import com.ng.xerathcore.annotation.Xerath_PopToast; 4 | 5 | /** 6 | * 描述: 7 | * 8 | * @author Jzn 9 | * @date 2021/9/4 10 | */ 11 | public class ViewMethodUtil { 12 | 13 | /** 14 | * 弹出Toast 15 | */ 16 | @Xerath_PopToast(str = "测试Toast") 17 | public static void popToast() { 18 | System.out.println("popToast"); 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/utils/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.utils; 2 | 3 | /** 4 | * 描述: 5 | * 6 | * @author Jzn 7 | * @date 2021/9/4 8 | */ 9 | public class LogUtil { 10 | private static final String TAG = "[ Xerath ] "; 11 | 12 | public static void print(String s) { 13 | System.out.println(TAG + s); 14 | } 15 | 16 | public static void printPre(String s) { 17 | System.out.println(TAG + "预处理 " + s); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #353535 5 | #353535 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FF888888 10 | #FFFFFFFF 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/MyApp.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath; 2 | 3 | import android.app.Application; 4 | 5 | import com.ng.xerathcore.XerathEngine; 6 | 7 | /** 8 | * @author : jiangzhengnan.jzn 9 | * @creation : 2021/09/20 10 | * @description : 11 | */ 12 | public class MyApp extends Application { 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | //框架初始化 18 | XerathEngine.getInstance().init(getApplicationContext()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_CallChain.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/09/15 11 | * @description :调用链路捕获 12 | */ 13 | @Retention(RetentionPolicy.CLASS) 14 | @Target(ElementType.METHOD) 15 | public @interface Xerath_CallChain { 16 | } 17 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_TryCatch.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/09/15 11 | * @description :异常捕获 12 | */ 13 | @Retention(RetentionPolicy.CLASS) 14 | @Target(ElementType.METHOD) 15 | public @interface Xerath_TryCatch { 16 | } 17 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_CalculateTime.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/08/27 11 | * @description :统计耗时注解 12 | */ 13 | @Retention(RetentionPolicy.CLASS) 14 | @Target(ElementType.METHOD) 15 | public @interface Xerath_CalculateTime { 16 | } 17 | 18 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_CollectParams.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/08/27 11 | * @description : 12 | * 参数统计 13 | * 统计方法的入参和出参 14 | */ 15 | @Retention(RetentionPolicy.CLASS) 16 | @Target(ElementType.METHOD) 17 | public @interface Xerath_CollectParams { 18 | } 19 | 20 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_LimitCall.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/09/15 11 | * @description :重复点击 12 | */ 13 | @Retention(RetentionPolicy.CLASS) 14 | @Target(ElementType.METHOD) 15 | public @interface Xerath_LimitCall { 16 | 17 | long time() default 0L; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_PopToast.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/09/15 11 | * @description :弹出Toast 12 | */ 13 | @Retention(RetentionPolicy.CLASS) 14 | @Target(ElementType.METHOD) 15 | public @interface Xerath_PopToast { 16 | 17 | String str() default ""; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /MyTask: -------------------------------------------------------------------------------- 1 | 0.增加tree 和core 分类的api包 2 | 3 | 0.增加覆盖率工具 4 | 5 | 1.如何方便的修改接入的三方sdk代码? 6 | 7 | 2.增加作用域的概念,在gradle中输入/初始化代码定义 8 | 方法生效/类生效/包下生效/全局生效 9 | 10 | 3.优化方法移除功能: 11 | 参考:https://github.com/bytedance/ByteX 12 | method-call-opt-plugin(干净地删除某些方法调用,如Log.d) 13 | 抖音Android包体积优化探索:从Class字节码入手精简DEX体积 14 | 参考实现:https://mp.weixin.qq.com/s/npT9MW4TQWH--fKsC_3NCQ(1. 查找终止指令位置) 15 | 16 | 4.包size优化部分插件 17 | 参考: 18 | https://ata.alibaba-inc.com/articles/202302?spm=ata.23639746.0.0.65e75902yLBT1C 19 | R文件优化:R Inline: 20 | https://ata.alibaba-inc.com/articles/193318?spm=ata.23639746.0.0.65e75902yLBT1C -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/extension/ExtConstant.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.extension; 2 | 3 | import com.ng.xerathlib.extension.bean.TrackMethodStack; 4 | import com.ng.xerathlib.extension.bean.TransformExt; 5 | 6 | public class ExtConstant { 7 | public static final String XERATH_BASE_EXT = "xerathTransformExt"; 8 | 9 | public static final String TRACK_METHOD_STACK = "track_method_stack"; 10 | 11 | //工程基础配置 12 | public static TransformExt sTransformExt; 13 | 14 | //方法栈抓取功能参数 15 | public static TrackMethodStack sTrackMethodStack; 16 | } 17 | -------------------------------------------------------------------------------- /XerathLib/src/main/groovy/com/ng/xerathlib/transform/util/PkgUtils.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.transform.util; 2 | 3 | /** 4 | * @author : jiangzhengnan 5 | * @creation : 2021/11/16 6 | * @description : 7 | */ 8 | public class PkgUtils { 9 | private static final String MY_PKG_NAME = "com.ng"; 10 | 11 | private static boolean isContainer(String className, String[] arrays) { 12 | for (String temp : arrays) { 13 | if (className.contains(temp)) { 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/target/base/ITargetPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.target.base; 2 | 3 | import com.ng.xerathlib.hook.params.HookParams; 4 | 5 | import org.objectweb.asm.MethodVisitor; 6 | 7 | public interface ITargetPlug { 8 | 9 | void init(HookParams params); 10 | 11 | void onHookMethodStart(MethodVisitor mv); 12 | 13 | void onHookMethodReturn(int opcode, MethodVisitor mv); 14 | 15 | void onHookMethodEnd(MethodVisitor mv); 16 | 17 | boolean onVisitMethodInsn(MethodVisitor mv, int opcode, String owner, String name, String desc, boolean itf); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /.idea/deploymentTargetDropDown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/asm/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.asm; 2 | 3 | public class Parameter { 4 | 5 | public final String name; 6 | public final String desc; 7 | public final int index; 8 | 9 | public Parameter(String name, String desc, int index){ 10 | this.name = name; 11 | this.desc = desc; 12 | this.index = index; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "Parameter{" + 18 | "name='" + name + '\'' + 19 | ", desc='" + desc + '\'' + 20 | ", index=" + index + 21 | '}'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/utils/Parameter.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.utils; 2 | 3 | public class Parameter { 4 | 5 | public final String name; 6 | public final String desc; 7 | public final int index; 8 | 9 | public Parameter(String name, String desc, int index){ 10 | this.name = name; 11 | this.desc = desc; 12 | this.index = index; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "Parameter{" + 18 | "name='" + name + '\'' + 19 | ", desc='" + desc + '\'' + 20 | ", index=" + index + 21 | '}'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/ui/adapter/ItemInfo.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.ui.adapter; 2 | 3 | /** 4 | * 描述: 5 | * 6 | * @author Jzn 7 | * @date 2020-04-11 8 | */ 9 | 10 | import android.view.View; 11 | 12 | import androidx.fragment.app.Fragment; 13 | 14 | 15 | public class ItemInfo { 16 | public String name; 17 | public Fragment fragment; 18 | 19 | @Override 20 | public String toString() { 21 | return "ItemInfo{" + 22 | "name='" + name + '\'' + 23 | '}'; 24 | } 25 | 26 | public ItemInfo(String name, Fragment fragment) { 27 | this.name = name; 28 | this.fragment = fragment; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/utils/CoreUtils.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.utils; 2 | 3 | import com.ng.xerathcore.constants.PlugConstant; 4 | 5 | /** 6 | * @author : jiangzhengnan.jzn 7 | * @creation : 2021/09/19 8 | * @description : 9 | */ 10 | public class CoreUtils { 11 | 12 | public static boolean needLimitCall(long time) { 13 | long lastTime = SpUtil.getLongValue(PlugConstant.SpName.LIMIT_CALL_TIME,0); 14 | if (System.currentTimeMillis() - lastTime < time) { 15 | return true; 16 | } 17 | SpUtil.putLongValue(PlugConstant.SpName.LIMIT_CALL_TIME,System.currentTimeMillis()); 18 | return false; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/func/chain/ChainA.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.func.chain; 2 | 3 | import com.ng.xerathcore.annotation.Xerath_CallChain; 4 | 5 | /** 6 | * @author : jiangzhengnan.jzn 7 | * @creation : 2021/09/25 8 | * @description : 9 | */ 10 | public class ChainA { 11 | public String a_params = "a_params"; 12 | 13 | public ChainB child; 14 | 15 | @Xerath_CallChain 16 | public void doSomeThing() { 17 | //hook完整调用链路 18 | //CoreHelper.catchCallChain(this); 19 | } 20 | 21 | @Xerath_CallChain 22 | public static void doSomeThing2() { 23 | //hook完整调用链路,static下,默认会不处理,防止crash 24 | //CoreHelper.catchCallChain(this); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /repo/com/ng/xerathlib/XerathCore/1.0.1/XerathCore-1.0.1.pom: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.ng.xerathlib 6 | XerathCore 7 | 1.0.1 8 | aar 9 | 10 | 11 | androidx.appcompat 12 | appcompat 13 | 1.3.1 14 | compile 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/utils/JsonPrinter.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.utils; 2 | 3 | 4 | import androidx.annotation.NonNull; 5 | import androidx.annotation.Nullable; 6 | 7 | import com.ng.xerathcore.CoreHelper; 8 | 9 | import org.json.JSONException; 10 | 11 | /** 12 | * @author : jiangzhengnan.jzn@alibaba-inc.com 13 | * @creation : 2021/10/06 14 | * @description : 15 | */ 16 | public class JsonPrinter { 17 | 18 | public static void print(@NonNull String name, @Nullable Object value) throws JSONException { 19 | if (value != null) { 20 | CoreHelper.catchLog("输入json . name:" + name + " value:" + value.toString()); 21 | } else { 22 | CoreHelper.catchLog("输入json value 为空"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/extension/bean/TransformExt.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.extension.bean; 2 | 3 | /** 4 | * 5 | */ 6 | public class TransformExt { 7 | //默认debug 环境 8 | public RunScene runVariant = RunScene.DEBUG; 9 | 10 | //是否开启注解功能,默认允许 11 | public boolean enableAnnotation = true; 12 | 13 | public boolean enableLog = true; 14 | 15 | @Override 16 | public String toString() { 17 | return "TransformExt{" + 18 | "runVariant=" + runVariant + 19 | ", enableAnnotation=" + enableAnnotation + 20 | ", enableLog=" + enableLog + 21 | '}'; 22 | } 23 | 24 | public enum RunScene { 25 | DEBUG, //demo 环境使用 26 | RELEASE 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/func/chain/ChainD.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.func.chain; 2 | 3 | import com.ng.xerathcore.CoreHelper; 4 | 5 | import org.json.JSONException; 6 | import org.json.JSONObject; 7 | 8 | /** 9 | * @author : jiangzhengnan.jzn 10 | * @creation : 2021/09/25 11 | * @description : 12 | */ 13 | public class ChainD extends ChainB { 14 | public JSONObject chainDJson; 15 | 16 | /** 17 | * 获取指定返回值或者指定参数的调用链路 18 | * 不能用static修饰! 19 | */ 20 | public JSONObject getCallChain() { 21 | chainDJson = new JSONObject(); 22 | try { 23 | chainDJson.put("ChainD_key", "ChainD_value"); 24 | } catch (JSONException e) { 25 | e.printStackTrace(); 26 | } 27 | return chainDJson; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /XerathLib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'groovy' 2 | apply plugin: 'maven' 3 | apply plugin: 'java' 4 | apply plugin : 'maven-publish' 5 | 6 | java { 7 | sourceCompatibility = JavaVersion.VERSION_1_8 8 | targetCompatibility = JavaVersion.VERSION_1_8 9 | } 10 | 11 | dependencies { 12 | //gradle sdk 13 | implementation gradleApi() 14 | //groovy sdk 15 | implementation localGroovy() 16 | //添加 gradle 17 | implementation 'com.android.tools.build:gradle:3.6.1' 18 | implementation 'org.ow2.asm:asm:9.2' 19 | implementation 'org.ow2.asm:asm-commons:9.1' 20 | } 21 | 22 | group = 'com.ng.xerathlib' 23 | version = "1.0.0" 24 | 25 | //打包上传到本地 26 | uploadArchives { 27 | repositories { 28 | flatDir { 29 | dirs '../repo/' 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/annotation/plug/base/IAnnotationPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.annotation.plug.base; 2 | 3 | import com.ng.xerathlib.hook.params.HookParams; 4 | 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.commons.LocalVariablesSorter; 7 | 8 | /** 9 | * 描述:注解处理器 10 | * 11 | * @author Jzn 12 | * @date 2021/9/14 13 | */ 14 | public interface IAnnotationPlug { 15 | 16 | void init(HookParams params); 17 | 18 | void onHookMethodStart(MethodVisitor mv); 19 | 20 | void onHookMethodReturn(int opcode,MethodVisitor mv); 21 | 22 | void onHookMethodEnd(MethodVisitor mv); 23 | 24 | boolean onVisitMethodInsn(MethodVisitor mv, int opcode, String owner, String name, String desc, boolean itf); 25 | 26 | void setLineNumber(int lineNumber); 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /XerathCore/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /XerathLib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/ui/fragment/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.ui.fragment 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.fragment.app.Fragment 8 | 9 | /** 10 | * 描述: 11 | * @author Jzn 12 | * @date 2020-06-12 13 | */ 14 | abstract class BaseFragment :Fragment() { 15 | 16 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 17 | return inflater.inflate(getLayoutId(), container, false) 18 | } 19 | 20 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 21 | super.onViewCreated(view, savedInstanceState) 22 | initViewsAndEvents(view) 23 | } 24 | 25 | abstract fun initViewsAndEvents(v: View) 26 | 27 | abstract fun getLayoutId(): Int 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/ui/view/rounded/Corner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Vincent Mi 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.ng.xerath.ui.view.rounded; 18 | 19 | public interface Corner { 20 | int TOP_LEFT = 0; 21 | int TOP_RIGHT = 1; 22 | int BOTTOM_RIGHT = 2; 23 | int BOTTOM_LEFT = 3; 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /XerathLib/src/androidTest/java/com/ng/xerathlib/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("com.ng.xerathlib.test", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_MethodRemove.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/09/15 11 | * @description : 12 | * 方法移除 13 | * removeMethods 待移除的方法 14 | * 例如: 15 | * 16 | * @Xerath_MethodRemove( 17 | * removeMethods = {"org/json/JSONObject|put|(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;"} 18 | * ) 19 | * public void someMethod() { 20 | * ... 21 | * } 22 | * 23 | * 按owner,name,desc的顺序,都以 | 分割,有多个的话以数组形式输入 24 | * 25 | */ 26 | @Retention(RetentionPolicy.CLASS) 27 | @Target(ElementType.METHOD) 28 | public @interface Xerath_MethodRemove { 29 | 30 | String[] removeMethods() default {}; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | -------------------------------------------------------------------------------- /app/plugin-rule.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | flatDir { 6 | dirs './repo/' 7 | } 8 | // 添加本地maven地址配置 9 | maven { 10 | url uri("${rootProject.projectDir}/repo") 11 | } 12 | maven { 13 | url 'https://storage.googleapis.com/r8-releases/raw' 14 | } 15 | } 16 | dependencies { 17 | classpath 'com.android.tools.build:gradle:4.2.2' 18 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31" 19 | //引入自定义插件 20 | classpath "com.ng.xerathlib:xerathlib:1.0.0" 21 | } 22 | } 23 | 24 | apply plugin: 'ng-xerath-plugin' 25 | xerathTransformExt { 26 | enableAnnotation = true 27 | runVariant = 'DEBUG' 28 | } 29 | 30 | track_method_stack{ 31 | enable = false 32 | targetPackageList = ['com.bumptech.glide'] 33 | targetClassList = ['com.ng.xerath.func.DataMethodUtil'] 34 | logTag = 'nangua' 35 | } -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 22 | 23 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_MethodCompleteRemove.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2022/03/03 11 | * @description : 12 | * 方法完全移除 13 | * (参数定义+方法调用) 14 | * removeMethods 待移除的方法 15 | * 例如: 16 | * 17 | * @Xerath_MethodRemove( 18 | * removeMethods = {"org/json/JSONObject|put|(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;"} 19 | * ) 20 | * public void someMethod() { 21 | * ... 22 | * } 23 | * 24 | * 按owner,name,desc的顺序,都以 | 分割,有多个的话以数组形式输入 25 | * 26 | * 编译期间优化掉项目所有调用了配置中配置的方法调用(包含参数形成指令) 27 | * 28 | */ 29 | @Retention(RetentionPolicy.CLASS) 30 | @Target(ElementType.METHOD) 31 | public @interface Xerath_MethodCompleteRemove { 32 | 33 | String[] removeMethods() default {}; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/utils/ThreadUtil.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.utils; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | 6 | /** 7 | * @author : jiangzhengnan.jzn 8 | * @creation : 2021/09/20 9 | * @description : 10 | */ 11 | public class ThreadUtil { 12 | /** 13 | * 主线程的Handler 14 | */ 15 | private static Handler sMainHandler; 16 | 17 | private static Handler getMainHandler() { 18 | if (null == sMainHandler) { 19 | sMainHandler = new Handler(Looper.getMainLooper()); 20 | } 21 | return sMainHandler; 22 | } 23 | 24 | public static void runOnUiThread(Runnable action) { 25 | if (Thread.currentThread() != Looper.getMainLooper().getThread()) { 26 | Handler handler = getMainHandler(); 27 | handler.post(action); 28 | } else { 29 | action.run(); 30 | } 31 | } 32 | 33 | public static void runThread(Runnable action) { 34 | new Thread(action).start(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/func/TrackMethodStackHelper.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.func; 2 | 3 | import android.util.Log; 4 | 5 | import com.ng.xerathcore.CoreHelper; 6 | 7 | /** 8 | * @author : jiangzhengnan.jzn@alibaba-inc.com 9 | * @creation : 2022/05/29 10 | * @description : 11 | * 超过5秒自动重置时间计算 12 | */ 13 | public class TrackMethodStackHelper { 14 | private static long firstTime = 0; 15 | private static long lastTime = 0; 16 | 17 | public static void callMethod(String methodInfo) { 18 | String timeStr = ""; 19 | long timeConsuming = 0; 20 | long nowTime = System.currentTimeMillis(); 21 | if (nowTime - firstTime > 5000) { 22 | //当前为初次调用 23 | lastTime = nowTime; 24 | firstTime = nowTime; 25 | } 26 | timeConsuming = nowTime - lastTime; 27 | lastTime = nowTime; 28 | 29 | timeStr = "pre:" + timeConsuming + "ms all:" + (nowTime - firstTime) + "ms"; 30 | String result = timeStr + " " + methodInfo; 31 | Log.d("xerath", result); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | # When configured, Gradle will run in incubating parallel mode. 10 | # This option should only be used with decoupled projects. More details, visit 11 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 12 | # org.gradle.parallel=true 13 | # AndroidX package structure to make it clearer which packages are bundled with the 14 | # Android operating system, and which are packaged with your app"s APK 15 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 16 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 17 | android.useAndroidX=true 18 | android.enableJetifier=true 19 | 20 | BUILD_DEV=true 21 | 22 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/annotation/Xerath_MethodReplace.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/09/15 11 | * @description : 12 | * 方法替换 13 | * replaceMethods 待替换的方法 14 | * targetMethods 需要被替换成的目标方法 15 | * 例如: 16 | * 17 | * @Xerath_MethodReplace( 18 | * replaceMethods = {"org/json/JSONObject|put|(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;"}, 19 | * targetMethods = {"com/ng/xerathcore/utils/JsonPrinter|print|(Ljava/lang/String;Ljava/lang/Object;)V"} 20 | * ) 21 | * public void someMethod() { 22 | * ... 23 | * } 24 | * 25 | * 按owner,name,desc的顺序,都以 | 分割,有多个的话以数组形式输入 26 | * replaceMethods与targetMethods必须成对存在! 27 | * 28 | */ 29 | @Retention(RetentionPolicy.CLASS) 30 | @Target(ElementType.METHOD) 31 | public @interface Xerath_MethodReplace { 32 | 33 | String[] targetMethods() default {}; 34 | 35 | String[] replaceMethods() default {}; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/func/member/TestMember1.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.func.member; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | /** 7 | * @author : jiangzhengnan.jzn@alibaba-inc.com 8 | * @creation : 2021/10/06 9 | * @description : 10 | */ 11 | public class TestMember1 { 12 | public JSONObject json1; 13 | public static JSONObject staticJson1; 14 | 15 | public void test() { 16 | //成员变量 和 类变量 17 | try { 18 | json1 = new JSONObject(); 19 | json1.put("name_1", "jzn"); 20 | staticJson1 = new JSONObject(); 21 | staticJson1.put("name_2", "lili"); 22 | } catch (JSONException e) { 23 | e.printStackTrace(); 24 | } 25 | 26 | //临时变量 27 | JSONObject json3 = new JSONObject(); 28 | try { 29 | json3.put("name_3", "haha"); 30 | } catch (JSONException e) { 31 | e.printStackTrace(); 32 | } 33 | 34 | try { 35 | JSONObject json4 = new JSONObject(); 36 | json4.put("name_4", "haha"); 37 | } catch (JSONException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /XerathCore/src/main/java/com/ng/xerathcore/XerathEngine.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathcore; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | import com.ng.xerathcore.utils.SpUtil; 7 | 8 | /** 9 | * 描述: 10 | * 数据收集 框架 11 | * 12 | * @author Jzn 13 | * @date 2021/9/5 14 | */ 15 | public class XerathEngine { 16 | private Context mContext; 17 | 18 | private static XerathEngine mInstance; 19 | 20 | private XerathEngine() { 21 | } 22 | 23 | public static XerathEngine getInstance() { 24 | if (mInstance == null) { 25 | synchronized (XerathEngine.class) { 26 | if (mInstance == null) { 27 | mInstance = new XerathEngine(); 28 | } 29 | } 30 | } 31 | return mInstance; 32 | } 33 | 34 | public void init(Context context) { 35 | mContext = context; 36 | SpUtil.init(mContext); 37 | } 38 | 39 | public Context getContext() { 40 | return mContext; 41 | } 42 | 43 | public void showToast(String str) { 44 | if (mContext != null) { 45 | Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show(); 46 | } 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /XerathLib/src/main/groovy/com/ng/xerathlib/XerathTransformPlugin.groovy: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib 2 | 3 | import com.android.build.gradle.AppExtension 4 | import com.android.build.gradle.LibraryExtension 5 | import com.ng.xerathlib.transform.XerathTransform 6 | import org.gradle.api.Plugin 7 | import org.gradle.api.Project 8 | /** 9 | * 用于注册自定义 Transform 的插件 10 | */ 11 | class XerathTransformPlugin implements Plugin { 12 | 13 | @Override 14 | void apply(Project project) { 15 | println("======XerathTransformPlugin apply 插件开始注册 ======") 16 | registerForApp(project) 17 | //registerForLib(project) 18 | 19 | } 20 | 21 | /** 22 | * 注册 for android 工程 23 | */ 24 | static void registerForApp(Project project) { 25 | AppExtension appExtension = project.extensions.getByType(AppExtension.class) 26 | appExtension.registerTransform(new XerathTransform(project)) 27 | } 28 | 29 | /** 30 | * 注册 for android library 31 | */ 32 | static void registerForLib(Project project) { 33 | LibraryExtension appExtension = project.extensions.getByType(LibraryExtension.class) 34 | appExtension.registerTransform(new XerathTransform(project)) 35 | } 36 | } -------------------------------------------------------------------------------- /XerathCore/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | 5 | android { 6 | compileSdkVersion 31 7 | 8 | defaultConfig { 9 | minSdkVersion 16 10 | targetSdkVersion 31 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | consumerProguardFiles "consumer-rules.pro" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | compileOptions { 25 | sourceCompatibility JavaVersion.VERSION_1_8 26 | targetCompatibility JavaVersion.VERSION_1_8 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation 'androidx.appcompat:appcompat:1.3.1' 32 | } 33 | 34 | apply plugin: 'maven' 35 | 36 | uploadArchives{ 37 | repositories.mavenDeployer{ 38 | // 本地仓库路径 39 | repository(url: uri("${rootProject.projectDir}/repo")) 40 | // 唯一标识 41 | pom.groupId = "com.ng.xerathlib" 42 | // 项目名称 43 | pom.artifactId = "XerathCore" 44 | // 版本号 45 | pom.version = "1.0.0" 46 | } 47 | } -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/target/plug/TrackMethodStackPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.target.plug; 2 | 3 | import com.ng.xerathlib.extension.ExtConstant; 4 | import com.ng.xerathlib.hook.target.base.TargetPlug; 5 | import com.ng.xerathlib.utils.LogUtil; 6 | import org.apache.http.util.TextUtils; 7 | import org.objectweb.asm.MethodVisitor; 8 | 9 | import static org.objectweb.asm.Opcodes.INVOKESTATIC; 10 | 11 | public class TrackMethodStackPlug extends TargetPlug { 12 | 13 | @Override 14 | public void onHookMethodStart(final MethodVisitor mv) { 15 | if (!TargetPlugFilter.isNeedTrackMethodStack(mOwner)) { 16 | return; 17 | } 18 | LogUtil.print("TrackMethodStackPlug 实施注入 onHookMethodStart " + mOwner + " " + mMethodName + " " + mMethodDesc); 19 | String log = ""; 20 | if (ExtConstant.sTrackMethodStack != null && !TextUtils.isEmpty(ExtConstant.sTrackMethodStack.logTag)) { 21 | log = ExtConstant.sTrackMethodStack.logTag; 22 | } 23 | mv.visitLdcInsn(log + " " + mOwner + "/" + mMethodName + " " + mMethodDesc); 24 | mv.visitMethodInsn(INVOKESTATIC, "com/ng/xerathcore/func/TrackMethodStackHelper", "callMethod", "(Ljava/lang/String;)V", false); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/asm/visitor/TestClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.asm.visitor; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.ASM6; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/08/25 11 | * @description : 12 | */ 13 | public class TestClassVisitor extends ClassVisitor { 14 | private String className; 15 | 16 | public TestClassVisitor(ClassVisitor visitor) { 17 | super(ASM6, visitor); 18 | } 19 | 20 | @Override 21 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 22 | super.visit(version, access, name, signature, superName, interfaces); 23 | this.className = name; 24 | 25 | } 26 | 27 | @Override 28 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 29 | MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); 30 | if (name.equals("test")) { 31 | return new TestAdviceAdapter(ASM6, access, descriptor, methodVisitor); 32 | } 33 | return methodVisitor; 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/asm/visitor/TestPreLoadClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.asm.visitor; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.ASM6; 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/08/25 11 | * @description : 12 | */ 13 | public class TestPreLoadClassVisitor extends ClassVisitor { 14 | private String className; 15 | 16 | 17 | public TestPreLoadClassVisitor(ClassVisitor visitor) { 18 | super(ASM6, visitor); 19 | } 20 | 21 | @Override 22 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 23 | super.visit(version, access, name, signature, superName, interfaces); 24 | this.className = name; 25 | 26 | } 27 | 28 | @Override 29 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 30 | MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions); 31 | if (name.equals("testParams")) { 32 | return new TestPreLoadAdviceAdapter(ASM6, methodVisitor); 33 | } 34 | return methodVisitor; 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/annotation/plug/base/AnnotationPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.annotation.plug.base; 2 | 3 | import com.android.annotations.NonNull; 4 | import com.ng.xerathlib.hook.params.HookParams; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | /** 9 | * 描述: 10 | * 11 | * @author Jzn 12 | * @date 2021/9/14 13 | */ 14 | public abstract class AnnotationPlug implements IAnnotationPlug { 15 | @NonNull 16 | protected HookParams mParams; 17 | 18 | @Override 19 | public void init(@NonNull HookParams params) { 20 | this.mParams = params; 21 | } 22 | 23 | protected boolean isStaticMethod() { 24 | return ((Opcodes.ACC_STATIC & mParams.mMethodAccess) != 0); 25 | } 26 | 27 | @Override 28 | public void onHookMethodStart(MethodVisitor mv) { 29 | 30 | } 31 | 32 | @Override 33 | public void onHookMethodReturn(int opcode, MethodVisitor mv) { 34 | 35 | } 36 | 37 | @Override 38 | public void onHookMethodEnd(MethodVisitor mv) { 39 | 40 | } 41 | 42 | @Override 43 | public boolean onVisitMethodInsn(MethodVisitor mv, int opcode, String owner, String name, String desc, boolean itf) { 44 | return false; 45 | } 46 | 47 | @Override 48 | public void setLineNumber(int lineNumber) { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/annotation/plug/PopToastPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.annotation.plug; 2 | 3 | import com.ng.xerathlib.hook.XerathHookHelper; 4 | import com.ng.xerathlib.hook.annotation.plug.base.AnnotationPlug; 5 | 6 | import org.objectweb.asm.Label; 7 | import org.objectweb.asm.MethodVisitor; 8 | import org.objectweb.asm.Opcodes; 9 | import org.objectweb.asm.commons.LocalVariablesSorter; 10 | 11 | /** 12 | * @author : jiangzhengnan.jzn 13 | * @creation : 2021/09/20 14 | * @description : 15 | */ 16 | public class PopToastPlug extends AnnotationPlug { 17 | 18 | 19 | @Override 20 | public void onHookMethodStart(MethodVisitor mv) { 21 | String showStr = (String) mParams.getAnnotationParams("str"); 22 | Label label0 = new Label(); 23 | mv.visitLabel(label0); 24 | mv.visitLineNumber(0, label0); 25 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/ng/xerathcore/XerathEngine", "getInstance", "()Lcom/ng/xerathcore/XerathEngine;", false); 26 | mv.visitLdcInsn(showStr + ""); 27 | mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "com/ng/xerathcore/XerathEngine", "showToast", "(Ljava/lang/String;)V", false); 28 | } 29 | 30 | @Override 31 | public void onHookMethodReturn(int opcode, MethodVisitor mv) { 32 | 33 | } 34 | 35 | @Override 36 | public void onHookMethodEnd(MethodVisitor mv) { 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/HookLifeCycle.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook; 2 | 3 | import org.objectweb.asm.AnnotationVisitor; 4 | import org.objectweb.asm.FieldVisitor; 5 | import org.objectweb.asm.Label; 6 | import org.objectweb.asm.MethodVisitor; 7 | 8 | /** 9 | * @author : jiangzhengnan.jzn@alibaba-inc.com 10 | * @creation : 2022/05/15 11 | * @description : 12 | */ 13 | public interface HookLifeCycle { 14 | //class 15 | boolean onVisitClass(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces); 16 | 17 | void visitClassField(int access, String name, String descriptor, String signature, Object value); 18 | 19 | //class 是否修改class 20 | boolean isClassChanged(); 21 | 22 | //method 23 | void onVisitMethod(int access, String name, String descriptor, MethodVisitor methodVisitor, 24 | String owner); 25 | //method 是否打断方法 26 | boolean onVisitMethodInsn(MethodVisitor mv, int opcode, String owner, String name, String desc, boolean itf); 27 | 28 | void visitMethodCode(); 29 | 30 | void visitLineNumber(int line, Label start); 31 | 32 | boolean visitMethodAnnotation(String descriptor, boolean visible); 33 | 34 | void onHookMethodReturn(int opcode, MethodVisitor mv); 35 | 36 | void onHookMethodEnd(MethodVisitor mv); 37 | 38 | void visitEnd(); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/asm/tree/TreeClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.asm.tree; 2 | 3 | import com.ng.xerathlib.asm.base.BaseClassVisitor; 4 | 5 | import com.ng.xerathlib.hook.XerathHookManager; 6 | import org.objectweb.asm.ClassVisitor; 7 | import org.objectweb.asm.MethodVisitor; 8 | 9 | /** 10 | * @Project ASMCostTime 11 | * @date 2020/6/22 12 | * @describe 13 | * 单模式cv,不受框架约束 14 | */ 15 | public class TreeClassVisitor extends BaseClassVisitor { 16 | 17 | public TreeClassVisitor(ClassVisitor visitor) { 18 | super(visitor); 19 | } 20 | 21 | @Override 22 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 23 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 24 | if (!isInterface && mv != null && !name.equals("")) { 25 | //LogUtil.print("方法:" + name + " des:" + descriptor + " "); 26 | //强行测试接入方法移除 todo 改为注解 27 | if (name.contains("tryRemoveMethod")) { 28 | mv = new RemoveMethodCallOptMethodVisitor(mv, access, name, descriptor, signature, exceptions); 29 | changed = true; 30 | } 31 | } 32 | return mv; 33 | } 34 | 35 | @Override 36 | public void visitEnd() { 37 | super.visitEnd(); 38 | XerathHookManager.getInstance().removeHelper(owner); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/asm/jar/JarHookMethodVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.asm.jar; 2 | 3 | 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | 8 | /** 9 | * @author : jiangzhengnan 10 | * @creation : 2021/08/25 11 | * @description : 12 | * 负责注入 13 | */ 14 | public class JarHookMethodVisitor extends MethodVisitor implements Opcodes { 15 | 16 | private int mMethodAccess; 17 | private boolean isStaticMethod; 18 | 19 | //参数 20 | private String mClassName; 21 | private String mMethodName; 22 | private String mMethodDesc; 23 | private String mMethodSignature; 24 | 25 | protected JarHookMethodVisitor(int api, int access, String className, String methodName, String descriptor, 26 | String signature, MethodVisitor methodVisitor) { 27 | super(api, methodVisitor); 28 | mClassName = className; 29 | mMethodName = methodName; 30 | mMethodDesc = descriptor; 31 | mMethodSignature = signature; 32 | mMethodAccess = access; 33 | isStaticMethod = ((Opcodes.ACC_STATIC & access) != 0); 34 | } 35 | 36 | @Override 37 | public void visitCode() { 38 | super.visitCode(); 39 | } 40 | 41 | @Override 42 | public void visitVarInsn(int opcode, int var) { 43 | super.visitVarInsn(opcode, var); 44 | if ((opcode >= IRETURN && opcode <= RETURN) || opcode == ATHROW) { 45 | return; 46 | } 47 | 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/asm/preload/PreLoadClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.asm.preload; 2 | 3 | import com.ng.xerathlib.asm.base.BaseClassVisitor; 4 | import org.objectweb.asm.ClassVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | 7 | import static org.objectweb.asm.Opcodes.ACC_INTERFACE; 8 | 9 | /** 10 | * @author : jiangzhengnan 11 | * @creation : 2021/08/25 12 | * @description : 13 | * 预加载数据 ClassVisitor 14 | */ 15 | public class PreLoadClassVisitor extends BaseClassVisitor { 16 | 17 | public PreLoadClassVisitor(ClassVisitor visitor) { 18 | super(visitor); 19 | } 20 | 21 | @Override 22 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 23 | super.visit(version, access, name, signature, superName, interfaces); 24 | this.owner = name; 25 | isInterface = (access & ACC_INTERFACE) != 0; 26 | } 27 | 28 | @Override 29 | public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { 30 | MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions); 31 | if (!isInterface && mv != null && !name.equals("")) { 32 | //LogUtil.printPre("方法:" + name + " des:" + descriptor + " "); 33 | //将MethodVisitor交由 XerathPreLoadAdviceAdapter 代理 34 | mv = new PreLoadMethodAdapter(mHookHelper, access, name, descriptor, mv, owner); 35 | } 36 | return mv; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/asm/base/BaseClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.asm.base; 2 | 3 | import com.android.annotations.Nullable; 4 | import com.ng.xerathlib.hook.XerathHookHelper; 5 | import com.ng.xerathlib.hook.XerathHookManager; 6 | import org.objectweb.asm.ClassVisitor; 7 | 8 | import static org.objectweb.asm.Opcodes.ACC_ABSTRACT; 9 | import static org.objectweb.asm.Opcodes.ACC_INTERFACE; 10 | import static org.objectweb.asm.Opcodes.ASM6; 11 | 12 | /** 13 | * @Project ASMCostTime 14 | * @date 2020/6/22 15 | * @describe 16 | */ 17 | public class BaseClassVisitor extends ClassVisitor { 18 | 19 | public boolean changed; 20 | public String owner; 21 | public boolean isInterface; 22 | public boolean isAbstract; 23 | 24 | @Nullable 25 | public XerathHookHelper mHookHelper; 26 | 27 | public BaseClassVisitor(ClassVisitor visitor) { 28 | super(ASM6, visitor); 29 | } 30 | 31 | @Override 32 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 33 | mHookHelper = XerathHookManager.getInstance().getHelper(name); 34 | cv.visit(version, access, name, signature, superName, interfaces); 35 | owner = name; 36 | isInterface = (access & ACC_INTERFACE) != 0; 37 | isAbstract = (access & ACC_ABSTRACT) != 0; 38 | } 39 | 40 | @Override 41 | public void visitEnd() { 42 | super.visitEnd(); 43 | } 44 | 45 | public boolean changed() { 46 | return mHookHelper.isClassChanged(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/extension/bean/TrackMethodStack.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.extension.bean; 2 | 3 | import java.util.List; 4 | 5 | import com.android.annotations.Nullable; 6 | 7 | /** 8 | * @author : jiangzhengnan.jzn@alibaba-inc.com 9 | * @creation : 2022/05/14 10 | * @description : 11 | * track_method_stack 12 | * 13 | * todo 14 | * 1.出入参 15 | * 2.进程+线程 16 | */ 17 | public class TrackMethodStack { 18 | public boolean enable; 19 | 20 | //目标包列表 (忽略类,只匹配包名) 21 | @Nullable 22 | public List targetPackageList; 23 | 24 | //目标类列表 (忽略包,只匹配类名) 25 | @Nullable 26 | public List targetClassList; 27 | 28 | //过滤包列表 (忽略类,只匹配包名)_ 29 | @Nullable 30 | public List blackPackageList; 31 | 32 | //过滤类列表 (忽略包,只匹配类名) 33 | @Nullable 34 | public List blackClassList; 35 | 36 | //耗时起点方法 (不传就从范围内调用的第一个方法开始统计耗时,格式包名+$+类名+$+方法名) 37 | @Nullable 38 | public String timeStartMethod; 39 | 40 | @Nullable 41 | public String logTag; 42 | 43 | @Override 44 | public String toString() { 45 | return "TrackMethodStack{" + 46 | "enable=" + enable + 47 | ", targetPackageList=" + targetPackageList + 48 | ", targetClassList=" + targetClassList + 49 | ", blackPackageList=" + blackPackageList + 50 | ", blackClassList=" + blackClassList + 51 | ", timeStartMethod='" + timeStartMethod + '\'' + 52 | ", logTag='" + logTag + '\'' + 53 | '}'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/target/plug/TargetPlugCreator.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.target.plug; 2 | 3 | import com.android.annotations.NonNull; 4 | import com.android.annotations.Nullable; 5 | import com.ng.xerathlib.hook.target.base.ITargetPlug; 6 | import com.ng.xerathlib.utils.LogUtil; 7 | import org.apache.http.util.TextUtils; 8 | 9 | /** 10 | * 描述: 11 | * plug构建规则 12 | */ 13 | public final class TargetPlugCreator { 14 | 15 | @Nullable 16 | public static ITargetPlug getPlug(String className) { 17 | if (TextUtils.isEmpty(className)) { 18 | return null; 19 | } 20 | return TargetPlugCreator.createPlug(className); 21 | } 22 | 23 | /** 24 | * 判断当前类/(方法待做)是否需要修改 25 | * [ Xerath ] --- 开始 hook className: com.ng.xerath.func.DataMethodUtil 26 | * [ Xerath ] XerathHookHelper-onVisitClass-清空 27 | *

28 | * [ Xerath ] className: com/ng/xerath/func/DataMethodUtil 29 | *

30 | * [ Xerath ] targetClassList: [DataMethodUtil] 31 | * [ Xerath ] targetPackageList: [com.ng.xerath.asm.func] 32 | */ 33 | @Nullable 34 | public static ITargetPlug createPlug(@NonNull String owner) { 35 | //LogUtil.print("TargetPlugCreator createPlug, owner:" + owner); 36 | ITargetPlug resultPlug = null; 37 | if (TargetPlugFilter.isNeedTrackMethodStack(owner)) { 38 | resultPlug = new TrackMethodStackPlug(); 39 | //LogUtil.print("TargetPlugCreator 符合条件:" + owner); 40 | } 41 | return resultPlug; 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/ng/xerath/asm/ASMShow.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerath.asm; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.annotation.Nullable; 5 | 6 | import com.ng.xerathcore.CoreHelper; 7 | 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | /** 12 | * @author : jiangzhengnan.jzn 13 | * @creation : 2021/09/16 14 | * @description : 15 | */ 16 | public class ASMShow { 17 | 18 | public void test() { 19 | // JSONObject testJson = new JSONObject(); 20 | // try { 21 | // testJson.put("name", "jzn"); 22 | // testJson.put("age", "26"); 23 | // testJson.put("height", "178"); 24 | // } catch (JSONException e) { 25 | // e.printStackTrace(); 26 | // } 27 | } 28 | 29 | // @NonNull 30 | // public JSONObject put(@NonNull String name, boolean value) throws JSONException { 31 | // return null; 32 | // } 33 | // 34 | // @NonNull 35 | // public JSONObject put(@NonNull String name, double value) throws JSONException { 36 | // return null; 37 | // } 38 | // 39 | // @NonNull 40 | // public JSONObject put(@NonNull String name, int value) throws JSONException { 41 | // return null; 42 | // 43 | // } 44 | // 45 | // @NonNull 46 | // public JSONObject put(@NonNull String name, long value) throws JSONException { 47 | // return null; 48 | // 49 | // } 50 | // 51 | // @NonNull 52 | // public JSONObject putObj(@NonNull String name, @Nullable Object value) throws JSONException { 53 | // return null; 54 | // } 55 | } 56 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/target/base/TargetPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.target.base; 2 | 3 | import com.ng.xerathlib.hook.params.HookParams; 4 | 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | import org.objectweb.asm.commons.LocalVariablesSorter; 8 | 9 | /** 10 | * 描述: 11 | * 12 | * @author Jzn 13 | * @date 2021/9/14 14 | */ 15 | public abstract class TargetPlug implements ITargetPlug { 16 | // 方法返回值类型描述符 17 | protected int mMethodAccess; 18 | protected String mMethodDesc; 19 | protected String mOwner; 20 | protected String mMethodName; 21 | protected LocalVariablesSorter mAdapter; 22 | 23 | @Override 24 | public void init(HookParams params) { 25 | this.mMethodAccess = params.mMethodAccess; 26 | this.mAdapter = params.mAdapter; 27 | this.mOwner = params.mOwner; 28 | this.mMethodName = params.mMethodName; 29 | this.mMethodDesc = params.mMethodDesc; 30 | } 31 | 32 | protected boolean isStaticMethod() { 33 | return ((Opcodes.ACC_STATIC & mMethodAccess) != 0); 34 | } 35 | 36 | @Override 37 | public void onHookMethodStart(MethodVisitor mv) { 38 | 39 | } 40 | 41 | @Override 42 | public void onHookMethodReturn(int opcode, MethodVisitor mv) { 43 | 44 | } 45 | 46 | @Override 47 | public void onHookMethodEnd(MethodVisitor mv) { 48 | 49 | } 50 | 51 | @Override 52 | public boolean onVisitMethodInsn(MethodVisitor mv, int opcode, String owner, String name, String desc, boolean itf) { 53 | return false; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/XerathHookManager.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | 5 | import com.android.annotations.NonNull; 6 | import com.android.annotations.Nullable; 7 | import com.ng.xerathlib.utils.LogUtil; 8 | 9 | /** 10 | * 避免多线程紊乱 11 | * 维护所有的XerathHookHelper 12 | */ 13 | public class XerathHookManager { 14 | private static XerathHookManager mInstance; 15 | 16 | private XerathHookManager() { 17 | mXerathHookHelperMap = new ConcurrentHashMap<>(); 18 | } 19 | 20 | public static XerathHookManager getInstance() { 21 | if (mInstance == null) { 22 | synchronized (XerathHookManager.class) { 23 | if (mInstance == null) { 24 | mInstance = new XerathHookManager(); 25 | } 26 | } 27 | } 28 | return mInstance; 29 | } 30 | 31 | @NonNull 32 | private final ConcurrentHashMap mXerathHookHelperMap; 33 | 34 | @Nullable 35 | public XerathHookHelper getHelper(@Nullable String owner) { 36 | if (owner == null || owner.length() == 0) { 37 | return null; 38 | } 39 | if (mXerathHookHelperMap.get(owner) == null) { 40 | mXerathHookHelperMap.put(owner, new XerathHookHelper()); 41 | } 42 | return mXerathHookHelperMap.get(owner); 43 | } 44 | 45 | public void removeHelper(@Nullable String owner) { 46 | if (owner == null || owner.length() == 0) { 47 | return; 48 | } 49 | mXerathHookHelperMap.remove(owner); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | apply plugin: 'kotlin-android' 5 | repositories { 6 | mavenCentral() 7 | } 8 | 9 | android { 10 | compileSdkVersion 31 11 | 12 | defaultConfig { 13 | applicationId "com.ng.xerath" 14 | minSdkVersion 16 15 | targetSdkVersion 31 16 | versionCode 1 17 | versionName "1.0" 18 | 19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | } 33 | 34 | dependencies { 35 | 36 | implementation 'androidx.appcompat:appcompat:1.3.1' 37 | implementation 'com.google.android.material:material:1.4.0' 38 | implementation 'androidx.constraintlayout:constraintlayout:2.1.0' 39 | 40 | //asm 41 | implementation 'org.ow2.asm:asm:9.2' 42 | implementation 'org.ow2.asm:asm-commons:9.1' 43 | 44 | implementation "androidx.core:core-ktx:1.7.0" 45 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31" 46 | 47 | if (project.BUILD_DEV) { 48 | api project(':XerathCore') 49 | } else { 50 | //core 引入注解依赖 51 | implementation 'com.ng.xerathlib:XerathCore:1.0.0' 52 | } 53 | 54 | implementation 'com.github.bumptech.glide:glide:4.9.0' 55 | 56 | 57 | } 58 | 59 | //引入插件 60 | apply from: project.file('plugin-rule.gradle') 61 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/hook/annotation/plug/CallChainPlug.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.hook.annotation.plug; 2 | 3 | import com.ng.xerathlib.hook.annotation.plug.base.AnnotationPlug; 4 | import com.ng.xerathlib.hook.params.HookParams; 5 | import com.ng.xerathlib.utils.LogUtil; 6 | 7 | import org.objectweb.asm.Label; 8 | import org.objectweb.asm.MethodVisitor; 9 | import org.objectweb.asm.Opcodes; 10 | import org.objectweb.asm.commons.LocalVariablesSorter; 11 | 12 | /** 13 | * @author : jiangzhengnan.jzn 14 | * @creation : 2021/09/20 15 | * @description : 16 | * 完整链路hook 17 | */ 18 | public class CallChainPlug extends AnnotationPlug { 19 | 20 | @Override 21 | public void init(HookParams params) { 22 | super.init(params); 23 | LogUtil.print("access:" + mParams.mMethodAccess); 24 | LogUtil.print("owner:" + mParams.mOwner); 25 | LogUtil.print("name:" + mParams.mMethodName); 26 | LogUtil.print("methodDesc:" + mParams.mMethodDesc); 27 | } 28 | 29 | @Override 30 | public void onHookMethodStart(MethodVisitor mv) { 31 | if (isStaticMethod()) { 32 | //防止静态方法下造成的crash 33 | return; 34 | } 35 | Label label0 = new Label(); 36 | mv.visitLabel(label0); 37 | mv.visitLineNumber(19, label0); 38 | mv.visitVarInsn(Opcodes.ALOAD, 0); 39 | mv.visitMethodInsn(Opcodes.INVOKESTATIC, "com/ng/xerathcore/CoreHelper", "catchCallChain", "(Ljava/lang/Object;)V", false); 40 | } 41 | 42 | @Override 43 | public void onHookMethodReturn(int opcode, MethodVisitor mv) { 44 | 45 | } 46 | 47 | @Override 48 | public void onHookMethodEnd(MethodVisitor mv) { 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /XerathLib/src/main/java/com/ng/xerathlib/asm/jar/JarClassVisitor.java: -------------------------------------------------------------------------------- 1 | package com.ng.xerathlib.asm.jar; 2 | 3 | import org.objectweb.asm.ClassVisitor; 4 | import org.objectweb.asm.FieldVisitor; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | import static org.objectweb.asm.Opcodes.ACC_INTERFACE; 9 | import static org.objectweb.asm.Opcodes.ASM6; 10 | 11 | /** 12 | * 处理jar包里的方法 13 | */ 14 | public final class JarClassVisitor extends ClassVisitor { 15 | private boolean isInterface; 16 | 17 | private String owner; 18 | 19 | JarClassVisitor(final ClassVisitor cv) { 20 | super(Opcodes.ASM6, cv); 21 | } 22 | 23 | @Override 24 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 25 | super.visit(version, access, name, signature, superName, interfaces); 26 | this.owner = name; 27 | isInterface = (access & ACC_INTERFACE) != 0; 28 | 29 | } 30 | 31 | @Override 32 | public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { 33 | return super.visitField(access, name, descriptor, signature, value); 34 | } 35 | 36 | @Override 37 | public MethodVisitor visitMethod(final int access, final String name, 38 | final String desc, final String signature, final String[] exceptions) { 39 | MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); 40 | if (!isInterface && mv != null && !name.equals("") 41 | ) { 42 | return new JarCatchMethodVisitor(ASM6, access, owner, name, desc, signature, mv); 43 | } 44 | return mv; 45 | } 46 | 47 | @Override 48 | public void visitEnd() { 49 | super.visitEnd(); 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 19 | 20 |