Meituan-Dianping / Robust

Robust is an Android HotFix solution with high compatibility and high stability. Robust can fix bugs immediately without a reboot.
Apache License 2.0
4.4k stars 805 forks source link

补丁打成功,但是找不到函数。java.lang.NoSuchMethodError #442

Closed ggx900706 closed 3 years ago

ggx900706 commented 3 years ago

异常类型:app运行时异常

手机型号:小米6、荣耀v10、木木模拟器、夜神模拟器

手机系统版本:4.4、6.0、miui11.0.2稳定版

Robust版本:0.4.99

Gradle版本:5.4.1

系统:macbook macOS10.15.1

堆栈/日志: 点击打补丁时日志如下: D/robust: patchManipulate list size is 1 D/robust: patch patch_info_name:com.ggx.test.robusttestapp.PatchesInfoImpl D/robust: current path:com.ggx.test.robusttestapp.SecActivity D/robust: oldClass :class com.ggx.test.robusttestapp.SecActivity fields 2 D/robust: current path:com.ggx.test.robusttestapp.SecActivity find:ChangeQuickRedirect com.ggx.test.robusttestapp.SecActivityPatchControl D/robust: changeQuickRedirectField set success com.ggx.test.robusttestapp.SecActivityPatchControl D/robust: patch finished E/ggx_test: on patch applied , true , test1 //我自己输出的日志,在onPatchApplied函数里面 D/robust: patch LocalPath:/storage/emulated/0/aPatch/patch.jar,apply result true

点击进入新页面后日志如下: W/System.err: java.lang.NoSuchMethodError: No direct method o()V in class Lcom/ggx/test/robusttestapp/SecActivityPatch; or its super classes (declaration of 'com.ggx.test.robusttestapp.SecActivityPatch' appears in /storage/emulated/0/aPatch/patch_temp.jar) W/System.err: at com.ggx.test.robusttestapp.SecActivityPatch.RobustPublicinitTextView(SecActivityPatch.java) W/System.err: at com.ggx.test.robusttestapp.SecActivityPatchControl.accessDispatch(PatchTemplate.java) W/System.err: at com.meituan.robust.PatchProxy.accessDispatch(PatchProxy.java:9) W/System.err: at com.meituan.robust.PatchProxy.proxy(PatchProxy.java:4) W/System.err: at com.ggx.test.robusttestapp.SecActivity.o(SecActivity.java) W/System.err: at com.ggx.test.robusttestapp.SecActivity.onCreate(SecActivity.java:4) W/System.err: at android.app.Activity.performCreate(Activity.java:6279) W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2396) W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2503) W/System.err: at android.app.ActivityThread.-wrap11(ActivityThread.java) W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1353) W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102) W/System.err: at android.os.Looper.loop(Looper.java:148) W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5539) W/System.err: at java.lang.reflect.Method.invoke(Native Method) W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:745) W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:635)

产生步骤: 1、新建应用,按照教程,集成gradle,编写新项目Activity,两个Activity,主Activity只有一个跳转按钮和一个打补丁按钮; 2、proguard文件如下: -dontwarn -keepattributes Signature,SourceFile,LineNumberTable -keepattributes Annotation -keeppackagenames -ignorewarnings -dontwarn android.support.v4.,CompatHoneycomb,com.tenpay.android. -optimizations !class/unboxing/enum,!code/simplification/arithmetic -keepclassmembers class { public static com.meituan.robust.ChangeQuickRedirect *; } 3、拷贝robut.xml文件到app下并修改包名,自定义 class PatchImp extends PatchManipulate并复制demo代码; 4、打包,安装应用; 5、复制mapping.txt,methodsMap.robust,打补丁,推补丁; 6、打开应用,点击打补丁,报错。。

第二个Activity代码的补丁有关的代码如下: @Modify private void initTextView() { // textView.setText(getOldText()); textView.setText("新textview内容,bug fixed"); }

private String getOldText() {
    return "原textview内容";
}

自定义的PatchImp类代码如下: public static String filePath = Environment.getExternalStorageDirectory() + "/aPatch/";

@Override
protected List<Patch> fetchPatchList(Context context) {
    Patch patch = new Patch();
    patch.setName("test1");
    patch.setLocalPath(filePath + "patch");
    patch.setTempPath(filePath + "patch");
    patch.setPatchesInfoImplClassFullName("com.ggx.test.robusttestapp.PatchesInfoImpl");

    List<Patch> result = new ArrayList<>();
    result.add(patch);
    return result;
}//其他函数直接从demo复制,com.ggx.test.robusttestapp为我的测试代码的包名,xml中也写的这个

mapping文件中有关找不到的那个函数的映射如下: com.ggx.test.robusttestapp.SecActivity -> com.ggx.test.robusttestapp.SecActivity: android.widget.TextView textView -> s 1:1:void ():11:11 -> java.lang.String getOldText() -> n 1:1:void initTextView():25:25 -> o 1:2:void onCreate(android.os.Bundle):16:17 -> onCreate 3:4:void onCreate(android.os.Bundle):19:20 -> onCreate

ggx900706 commented 3 years ago

自问自答。。已解决。。patch.setTempPath必须写私有目录的地址,否则就出现上面那个情况。。另外还有一个坑,修复之前的函数里面没有调用其他函数或者new对象,那么就不会修复,这个对一些工具类很不友好,建议更新