Tinker: Android 9加载Apache库crash

Created on 22 Oct 2018  ·  8Comments  ·  Source: Tencent/tinker

Issue/提问须知

在提交issue之前,我们应该先查询是否已经有相关的issue以及常见问题。提交issue时,我们需要写明issue的原因,以及编译或运行过程的日志(加载进程以及Patch进程)。issue需要以下面的格式:

```
异常类型:app运行时异常

手机型号:如:Google Pixel 2

手机系统版本:如:Android 9.0

tinker版本:如:1.9.9

gradle版本:如:3.1.2

是否使用热更新SDK: 否

系统:Windows

堆栈/日志:
31858-31858/tinker.sample.android E/AndroidRuntime: FATAL EXCEPTION: main
Process: tinker.sample.android, PID: 31858
java.lang.RuntimeException: Unable to start activity ComponentInfo{tinker.sample.android/tinker.sample.android.app.MainActivity}: java.lang.RuntimeException: Stub!
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2902)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3037)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1797)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6642)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.RuntimeException: Stub!
at org.apache.http.message.BasicNameValuePair.(BasicNameValuePair.java:6)
at tinker.sample.android.app.MainActivity.test(MainActivity.java:183)
at tinker.sample.android.app.MainActivity.onCreate(MainActivity.java:117)
at android.app.Activity.performCreate(Activity.java:7131)
at android.app.Activity.performCreate(Activity.java:7122)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2882)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3037) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1797) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6642) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

为了使用Apache的HTTP相关内容,在demo本地中加入org.apache.http.legacy.jar,MainActivity中触发调用:
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

List pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("key1", "value1"));
未加载补丁版本能正常运行,加载了补丁的版本在Android 9上必现crash,求助~

Most helpful comment

同遇到此问题,已解决。
依赖的三方库中有HttpClient ,引入的时候有人在项目中加入了org.apache.http.legacy.jar 。

解决方案:删除 org.apache.http.legacy.jar 。 用 useLibrary 'org.apache.http.legacy' 或者 想办法compileOnly org.apache.http.legacy.jar ,或者找一份 httpclient源码导入项目中、会增加包体积,并不会所谓『冲突』。
保证apk内没有legacy.jar class文件

问题原因 9.0 之前 /system/framework/org.apache.http.legacy.boot.jar 一直在 bootclasspath 中,在9.0 移除了。这个jar包出现在 app PathClassloader DexListPath 中。 tinker 在类 AndroidNClassLoader 方法 recreateDexPathList 在重建 DexPathList的时候有一个判断
if (!dexFile.getName().equals(baseApkFullPath)) {
continue;
}
这个判断会把原先 PathClassLoader 中的 /system/framework/org.apache.http.legacy.boot.jar 过滤掉。从而导致 在 findClass的时候 加载到打到 apk 内的 org.apache.http.legacy.jar (注意这个只是个头文件) 这个jar本来是只是参与编译的,现在他参与运行的 所以抛出了上述异常。假设没有将 org.apache.http.legacy.jar这个包打到apk内,在 super.findClass的时候会抛异常,tinker 让originClassLoader.loadClass(name) 并且originClassLoader 这个原先的 PathClassLoader 中是有/system/framework/org.apache.http.legacy.boot.jar 。分析到这我也说不清楚算不算tinker的bug了,如果正确使用httpclient的话,是不会有此问题的。以上方案针对targetSdk < 28 。
最后,请尽快迁移 httpclient。

All 8 comments

这个是不是P最新推送引起的问题

遇到同样的问题了,补丁生效后使用org.apache.http.legacy的地方会报错!崩溃,杀进程重启也不行,只有清数据删除补丁才行...

未加载补丁版本能正常运行,加载了补丁的版本在Android 9上必现crash。我也遇到了,同问~
希望Tinker团队给一下答复,如何调整或者避免。

好像是AndroidNClassLoader加载httpclient出现了某些问题,求解决方案。

同样的问题 Android 9 小米MIX2S 用的AsyncHttpClient

2 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2946)

3 ......
4 Caused by:
5 java.lang.RuntimeException:Stub!
6 org.apache.http.conn.scheme.SchemeRegistry.(SchemeRegistry.java:35)
7 com.loopj.android.http.a.a(AsyncHttpClient.java:213)
8 com.loopj.android.http.a.(AsyncHttpClient.java:179)
9 com.loopj.android.http.a.(AsyncHttpClient.java:149)

这个问题有两种解决方式:

  1. 去掉HttpClient包,把联网请求改成HTTPURLConnection的形式;
  2. 全局修改HttpClient包名和所有依赖,则不会出现包名冲突的问题。

同遇到此问题,已解决。
依赖的三方库中有HttpClient ,引入的时候有人在项目中加入了org.apache.http.legacy.jar 。

解决方案:删除 org.apache.http.legacy.jar 。 用 useLibrary 'org.apache.http.legacy' 或者 想办法compileOnly org.apache.http.legacy.jar ,或者找一份 httpclient源码导入项目中、会增加包体积,并不会所谓『冲突』。
保证apk内没有legacy.jar class文件

问题原因 9.0 之前 /system/framework/org.apache.http.legacy.boot.jar 一直在 bootclasspath 中,在9.0 移除了。这个jar包出现在 app PathClassloader DexListPath 中。 tinker 在类 AndroidNClassLoader 方法 recreateDexPathList 在重建 DexPathList的时候有一个判断
if (!dexFile.getName().equals(baseApkFullPath)) {
continue;
}
这个判断会把原先 PathClassLoader 中的 /system/framework/org.apache.http.legacy.boot.jar 过滤掉。从而导致 在 findClass的时候 加载到打到 apk 内的 org.apache.http.legacy.jar (注意这个只是个头文件) 这个jar本来是只是参与编译的,现在他参与运行的 所以抛出了上述异常。假设没有将 org.apache.http.legacy.jar这个包打到apk内,在 super.findClass的时候会抛异常,tinker 让originClassLoader.loadClass(name) 并且originClassLoader 这个原先的 PathClassLoader 中是有/system/framework/org.apache.http.legacy.boot.jar 。分析到这我也说不清楚算不算tinker的bug了,如果正确使用httpclient的话,是不会有此问题的。以上方案针对targetSdk < 28 。
最后,请尽快迁移 httpclient。

遇到了同样的问题。。
Maybe bug 77342775, looking for Lorg/apache/http/NameValuePair;
java.lang.ClassCastException: org.apache.http.message.BasicNameValuePair cannot be cast to org.apache.http.NameValuePair

Was this page helpful?
0 / 5 - 0 ratings