Skip to content

Repository files navigation


ASM-Task

目录

  1. 使用 Core&Tree Api 读取 ArrayList
  2. 使用 Core&Tree Api 生成 Main 类
  3. 使用 Core&Tree Api 输出方法的入参和出参
  4. 使用 Core&Tree Api 删除方法里面的日志输出语句
  5. 使用 Core&Tree Api 输出特定方法耗时
  6. 使用 Core&Tree Api 统一线程重命名
  7. 使用 Core&Tree Api 给特定方法加上 try-catch 块
  8. 使用 Core&Tree Api 替换方法调用,为系统类或第三方库代码兜底
  9. 使用 Core&Tree Api 进行序列化检查
  10. 使用 Core&Tree Api 检查是否有调用不存在的方法

任务一:读取 ArrayList 类

掌握最基础的 class 表现形式。

任务二:生成 Main 类

使用 ASM Api 生成以下 Main 类:

publicclassMain {
privatestaticfinalStringTAG = "Main";
publicstaticvoidmain(String[] args) {
System.out.println("Hello World.");
}
}

任务三:输出方法的入参和出参

修改前的 Java 文件:

publicclassPrintMethodParams {
publicStringprint(Stringname, intage) {
returnname + ": " + age;
}
}

目标生成的类文件,且需要验证反射该 class 文件的正确性:

publicclassPrintMethodParamsCoreClass {
publicPrintMethodParamsCoreClass() {
}
publicStringprint(Stringvar1, intvar2) {
System.out.println(var1);
System.out.println(var2);
Stringvar10000 = var1 + ": " + var2;
System.out.println(var10000);
returnvar10000;
}
}

任务四:删除方法里面的日志输出语句

修改前的 Java 文件:

publicclassDeleteLogInvoke {
publicStringprint(Stringname, intage) {
System.out.println(name);
Stringresult = name + ": " + age;
System.out.println(result);
System.out.println("Delete current line.");
System.out.println("name = " + name + ", age = " + age);
System.out.printf("name: %s%n", name);
System.out.println(String.format("age: %d", age));
returnresult;
}
}

目标生成的类文件,且需要验证反射该 class 文件的正确性:

publicclassDeleteLogInvokeCoreClass {
publicDeleteLogInvokeCoreClass() {
}
publicStringprint(Stringvar1, intvar2) {
Stringvar3 = var1 + ": " + var2;
returnvar3;
}
}

任务五:输出特定方法的方法耗时

修改前的 Java 文件:

publicclassMeasureMethodTime {
@MeasureTimepublicvoidmeasure() {
try {
Thread.sleep(2000);
} catch (InterruptedExceptione) {
thrownewRuntimeException(e);
}
}
}

目标生成的类文件,且需要验证反射该 class 的正确性:

publicclassMeasureMethodTimeCoreClass {
publicMeasureMethodTimeCoreClass() {
}
@MeasureTimepublicvoidmeasure() {
longvar1 = System.currentTimeMillis();
try {
Thread.sleep(2000L);
} catch (InterruptedExceptionvar8) {
RuntimeExceptionvar10000 = newRuntimeException(var8);
longvar4 = System.currentTimeMillis();
System.out.println(var4 - var1);
throwvar10000;
}
longvar6 = System.currentTimeMillis();
System.out.println(var6 - var1);
}
}

任务六:线程重命名

修改前的 Java 文件:

publicclassThreadReName {
publicstaticvoidmain(String[] args) {
// 不带线程名称newThread(newInternalRunnable()).start();
// 带线程名称Threadthread0 = newThread(newInternalRunnable(), "thread0");
System.out.println("thread0: " + thread0.getName());
thread0.start();
Threadthread1 = newThread(newInternalRunnable());
// 设置线程名字thread1.setName("thread1");
System.out.println("thread1: " + thread1.getName());
thread1.start();
}
}

目标生成的类文件,且需要验证反射该 class 的正确性:

publicclassThreadReNameCoreClass {
publicThreadReNameCoreClass() {
}
publicstaticvoidmain(String[] var0) {
(newShadowThread(newInternalRunnable(), "sample/ThreadReNameCoreClass#main-Thread-0")).start();
ShadowThreadvar1 = newShadowThread(newInternalRunnable(), "thread0", "sample/ThreadReNameCoreClass#main-Thread-1");
System.out.println("thread0: " + var1.getName());
var1.start();
ShadowThreadvar2 = newShadowThread(newInternalRunnable(), "sample/ThreadReNameCoreClass#main-Thread-2");
var2.setName(ShadowThread.makeThreadName("thread1", "sample/ThreadReNameCoreClass#main-Thread-3"));
System.out.println("thread1: " + var2.getName());
var2.start();
}
}

任务七:给特定方法加上 try-catch 块

修改前的 Java 文件:

publicclassCatchMethodInvoke {
publicintcalc() {
return1 / 0;
}
}

目标生成的类文件,且需要验证反射该 class 的正确性:

publicclassCatchMethodInvokeCoreClass {
publicCatchMethodInvokeCoreClass() {
}
publicintcalc() {
try {
return1 / 0;
} catch (Exceptionvar2) {
var2.printStackTrace();
return0;
}
}
}

任务八:使用 Core&Tree Api 替换方法调用,为系统类或第三方库代码兜底

这个任务的思路来源于:Booster 修复系统 Bug - Android 7.1 Toast 崩溃

其实延续上个任务的思路,为特定方法添加 try-catch 也能解决,但是 try-catch 过于粗暴,替换方法调用的方式灵活性更好些(其实在任务六里也有用到该思路)。

修改前的 Java 文件:

publicclassReplaceMethodInvoke {
publicstaticvoidmain(String[] args) {
// throw NPEnewToast().show();
}
}

目标生成的类文件,且需要验证反射该 class 的正确性:

publicclassReplaceMethodInvokeCoreClass {
publicReplaceMethodInvokeCoreClass() {
}
publicstaticvoidmain(String[] var0) {
ShadowToast.show(newToast(), "sample/ReplaceMethodInvokeCoreClass");
}
}

任务九:序列化检查

这个任务的思路来源于:ByteX - 序列化检查

对于 Java 的序列化,有以下几条规则需要遵守(也就是 IDEA Inspections 里的几条规则):

  1. 实现了 Serializable 的类未提供 serialVersionUID 字段
  2. 实现了 Serializable 的类包含非 transient、static 的字段,这些字段并未实现 Serializable 接口
  3. 未实现 Serializable 接口的类,包含 transient、serialVersionUID 字段
  4. 实现了 Serializable 的非静态内部类,它的外层类并未实现 Serializable 接口

针对以下代码:

publicclassSerializationCheckimplementsSerializable {
privateItemBean1itemBean1;
privateItemBean2itemBean2;
privatetransientItemBean3itemBean3;
privateStringname;
privateintage;
staticclassItemBean1 {
}
staticclassItemBean2implementsSerializable {
}
staticclassItemBean3 {
}
}

检查输出:

Attention: Non-serializablefield'itemBean1'inaSerializableclass [sample/SerializationCheckCoreClass]
Attention: This [sample/SerializationCheckCoreClass] classisserializable, butdoesnotdefinea'serialVersionUID'field.

任务十:检查是否有调用不存在的方法

这个任务的思路来源于:ByteX - 非法引用检查

不过示例里写的相对简单很多,怎么模拟引用找不到但编译不会报错的情况呢?我们可以借助于依赖方式:

 compileOnly(project(":library1"))
runtimeOnly(fileTree("libs") { include("*.jar") })

针对以下代码:

funmain() {
// throw IllegalAccessError:// class task_11.ReferCheckKt tried to access private method LibraryClass.testPrivateMethod()VLibraryClass().testPrivateMethod()
// throw NoSuchMethodError: LibraryClass.testModifyParamsMethod()VLibraryClass().testModifyParamsMethod()
// NoSuchMethodError: LibraryClass.testModifyReturnTypeMethod()VLibraryClass().testModifyReturnTypeMethod()
}

检查输出:

在 sample/ReferCheckTreeClass$testPrivateMethod 方法里监测到非法调用: IllegalAccessError: 试图调用 private final LibraryClass.testPrivateMethod()V 方法.
在 sample/ReferCheckTreeClass$testModifyParamsMethod 方法里监测到非法调用: NoSuchMethodError: 找不到 LibraryClass.testModifyParamsMethod()V 方法.
在 sample/ReferCheckTreeClass$testModifyReturnTypeMethod 方法里监测到非法调用: NoSuchMethodError: 找不到 LibraryClass.testModifyReturnTypeMethod()V 方法.

任务十一:

About

No description, website, or topics provided.

Resources

Stars

15 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages