Android 11 限制反射,如何破解?
https://github.com/Pangu-Immortal
先來分析一下問題出現(xiàn)的原因
我們看一眼Android 11 的源碼,如下:
static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis, jstring name, jobjectArray args) {// ……Handle<mirror::Method> result = hs.NewHandle(mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize>(soa.Self(),klass,soa.Decode<mirror::String>(name),soa.Decode<mirror::ObjectArray<mirror::Class>>(args),GetHiddenapiAccessContextFunction(soa.Self())));if (result == nullptr || ShouldDenyAccessToMember(result->GetArtMethod(), soa.Self())) {return nullptr;}return soa.AddLocalReference<jobject>(result.Get()); }如果 ShouldDenyAccessToMember 返回 true,那么就會(huì)返回 null,上層就會(huì)拋出方法找不到的異常。這里和 Android P 沒什么不同,只是把 ShouldBlockAccessToMember 改了個(gè)名而已。
ShouldDenyAccessToMember 會(huì)調(diào)用到 hiddenapi::ShouldDenyAccessToMember,該函數(shù)是這樣實(shí)現(xiàn)的:
原來的方案失效了能在 FirstExternalCallerVisitor 的 VisitFrame 方法中找到答案
bool VisitFrame() override REQUIRES_SHARED(Locks::mutator_lock_) {ArtMethod *m = GetMethod();......ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();if (declaring_class->IsBootStrapClassLoaded()) {......// 如果 PREVENT_META_REFLECTION_BLACKLIST_ACCESS 為 Enabled,跳過來自 java.lang.reflect.* 的訪問// 系統(tǒng)對(duì)“套娃反射”的限制的關(guān)鍵就在此ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>();if (declaring_class->IsInSamePackage(proxy_class) && declaring_class != proxy_class) {if (Runtime::Current()->isChangeEnabled(kPreventMetaReflectionBlacklistAccess)) {return true;}}}caller = m;return false; }我們看一下如何解決
我們采用的是第二種方案,有什么方法可以讓 VM 無法識(shí)別我的調(diào)用棧呢?這可以通過 JniEnv::AttachCurrentThread(…) 函數(shù)創(chuàng)建一個(gè)新的 Thread 來完成。
具體我們可以參考這:https://developer.android.com/training/articles/perf-jni
然后配合 std::async(…) 與 std::async::get(…) 就能搞定了。
下面是關(guān)鍵代碼:
// java 層直接用 jni 調(diào)用這個(gè)方法 static jobject Java_getDeclaredMethod(JNIEnv *env,jclass interface,jobject clazz,jstring method_name,jobjectArray params) {// ...... 省掉一些轉(zhuǎn)換代碼// 先用 std::async 調(diào)用 getDeclaredMethod_internal 方法auto future = std::async(&getDeclaredMethod_internal, global_clazz,global_method_name,global_params);auto result = future.get();return result; }static jobject getDeclaredMethod_internal(jobject clazz,jstring method_name,jobjectArray params) {// 這里就是一些普通的 jni 操作了JNIEnv *env = attachCurrentThread();jclass clazz_class = env->GetObjectClass(clazz);jmethodID get_declared_method_id = env->GetMethodID(clazz_class, "getDeclaredMethod","(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");jobject res = env->CallObjectMethod(clazz, get_declared_method_id,method_name, params);detachCurrentThread();return env->NewGlobalRef(res); }JNIEnv *attachCurrentThread() {JNIEnv *env;// AttachCurrentThread 核心在這里int res = _vm->AttachCurrentThread(&env, nullptr);return env; }https://github.com/Pangu-Immortal
總結(jié)
以上是生活随笔為你收集整理的Android 11 限制反射,如何破解?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jetpack CameraX 最新最全
- 下一篇: 对比Compose 、kotlin、fl