下面摘录自官方
从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口实施了限制。只要应用引用非 SDK 接口或尝试使用反射或 JNI 来获取其句柄,这些限制就适用。这些限制旨在帮助提升用户体验和开发者体验,为用户降低应用发生崩溃的风险,同时为开发者降低紧急发布的风险。如需详细了解有关此限制的决定,请参阅通过减少非 SDK 接口的使用来提高稳定性。
随着每个 Android 版本的发布,会有更多非 SDK 接口受到限制。 我们知道这些限制会影响您的发布工作流,同时我们希望确保您拥有相关工具来检测非 SDK 接口的使用情况、有机会向我们提供反馈,并且有时间根据相应新政策做出规划和调整。
为最大程度地降低非 SDK 使用限制对开发工作流的影响,我们将非 SDK 接口分成了几个名单,这些名单界定了非 SDK 接口使用限制的严格程度(取决于应用的目标 API 级别)。下表介绍了这些名单:
尽管您目前仍可以使用某些非 SDK 接口(取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。如果您的应用依赖于非 SDK 接口,建议您开始计划迁移到 SDK 接口或其他替代方案。如果您无法为应用中的功能找到无需使用非 SDK 接口的替代方案,我们建议您请求添加新的公共 API。
下表说明了当您的应用尝试访问屏蔽名单中的非 SDK 接口时可能会出现的预期行为。
1.谷歌建议开发者尽量使用公开的sdk接口,并没有禁止非sdk接口的使用
2.非sdk接口,开发者一般都是通过反射的机制进行使用,api>=28会进行限制,也就是说访问非sdk接口可能会失败
3.非sdk接口会进行等级分类,包括blacklist, greylist-max-x, greylist, whitelist等,其中greylist与whitelist不受限制
4.非sdk接口的等级可能会随着targetSdk以及系统sdk版本变化
Blacklist-api的配置文件一般在aops源码的aosp/frameworks/base/config/hiddenapi-force-blacklist.txt
以访问Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V为例
然后运行时抛出了异常NoSuchMethodException
非sdk接口,greylist以及whitelist不受限制,但是blacklist以及greylist-max-x会进行限制
这个是本文的主题,后面会通过手段达到目的
其内部调用了getMethod函数
第三个参数recursivePublicMethods为false,所以内部实际调用的是getDeclaredMethodInternal
getDeclaredMethodInternal为native函数,会调用到c++,源码可在art/runtime/native/java_lang_Class.cc中查找
大家可以留意一下art/runtime/native这个目录,包含了很多native-jni的函数实现
其内部调用了mirror::Class::GetDeclaredMethodInternal
源码中关键的地方做了标注,上述代码中有9个关键的地方,大家可自行查看,其中ShouldDenyAccessToMember为非sdk接口限制的关键函数
fn_get_access_context的源头是在java_lang_Class->getMethodIdInternal传过来的函数指针,即GetHiddenapiAccessContextFunction
也就是说,如果caller的domain值越小,能访问的hiddenapi范围越广。比如corePlatform能访问所有级别的api,但是application级别不能访问corePlatform以及platform级别的api。
###
这里返回了false(重点), 后边的代码省略,因为当前已经找到了两处返回false的地方(返回false表示可以访问)。
也就是说policy策略关闭时,可以自由访问hiddenapi,该方案可使用开源方案,但是需要适配不同的系统版本。
开源的方案是通过修改runtime内存实现的, 内存hidden_apipolicy的偏移值可因为系统版本,也可因为厂家定制导致不统一,所以该方案兼容性问题较大。
runtime->GetHiddenApiExemptions, 顾名思义:获取豁免的hiddenapi签名
该函数会遍历exemptions,只要有一个exemption,匹配当前访问的method->signature前缀,就可返回false。
无论MemberSignature的type_为field还是method,其返回值都是以class_name.c_str为前缀
另外,我们知道一个class的签名,形式都是如Ljava/lang/String;这种,肯定是以L开头的。
也就是说,想要调用setHiddenApiExemptions, 必须fake掉hiddenapi的限制。
所以看一下java_lang_Class中的GetHiddenapiAccessContextFunction
在此,domain_通过ComputeDomain初始化
直接搜索
代码中一共判断了5个文件位置,分别对应不同的domain
1.只是为了判断相关module的dir是否存在,一般都是存在的
2.artModule路径为/apex/com.android.art(android 11), 安卓10上的代码稍有区别
3.conscryptModule路径为/apex/com.android.conscrypt
4.apex的路径为/apex/
5.SystemFramework的路径为/system/framework
先随便找个debug的app看一下运行时apex路径都有哪些
这里有一个java.lang.System类,该类我们经常使用其加载so库,比如System.loadLibrary。
所以,我们可以通过System.loadLibrary,然后在native层的JNI_OnLoad中通过反射调用setHiddenApiExemptions(此时caller为java.lang.System.其domain级别为corePlatform),然后就可以随意访问hiddenapi了
核心代码:
名单 |
说明 |
屏蔽名单 (blacklist ) |
无论应用的目标 API 级别是什么,您都无法使用的非 SDK 接口。 如果您的应用尝试访问其中任何一个接口,系统就会抛出错误。 |
有条件屏蔽 (greylist-max-x ) |
从 Android 9(API 级别 28)开始,当有应用以该 API 级别为目标平台时,我们会在每个 API 级别分别限制某些非 SDK 接口。这些名单会以应用无法再访问该名单中的非 SDK 接口之前可以作为目标平台的最高 API 级别 (max-target-x ) 进行标记。例如,在 Android Pie 中未被屏蔽、但现在已被 Android 10 屏蔽的非 SDK 接口会列入 max-target-p (greylist-max-p ) 名单,其中的“p”表示 Pie 或 Android 9(API 级别 28)。如果您的应用尝试访问受目标 API 级别限制的接口,系统就会将此 API 视为已列入屏蔽名单。 |
不支持 (greylist ) |
当前不受限制且您的应用可以使用的非 SDK 接口。 但请注意,这些接口不受支持,可能会在未发出通知的情况下随时发生更改。预计这些接口在未来的 Android 版本中会被有条件地屏蔽,并列在 max-target-x 名单中。 |
SDK (whitelist ) |
已在 Android 框架软件包索引中正式记录、受支持并且可以自由使用的接口。 |
访问方式 |
结果 |
Dalvik 指令引用某个字段 |
抛出 NoSuchFieldError
|
Dalvik 指令引用某个方法 |
抛出 NoSuchMethodError
|
通过 Class.getDeclaredField() 或 Class.getField() 进行反射 |
抛出 NoSuchFieldException
|
通过 Class.getDeclaredMethod() 、Class.getMethod() 进行反射 |
抛出 NoSuchMethodException
|
通过 Class.getDeclaredFields() 、Class.getFields() 进行反射 |
结果中未获取到非 SDK 成员 |
通过 Class.getDeclaredMethods() 、Class.getMethods() 进行反射 |
结果中未获取到非 SDK 成员 |
通过 env->GetFieldID() 进行 JNI 调用 |
返回 NULL ,抛出 NoSuchFieldError
|
通过 env->GetMethodID() 进行 JNI 调用 |
返回 NULL ,抛出 NoSuchMethodError
|
/
/
android
-
11.0
.
0_r36
liuzhuangzhuang@virtualbox:~
/
work
/
aosp
/
frameworks
/
base$
liuzhuangzhuang@virtualbox:~
/
work
/
aosp
/
frameworks
/
base$ vim config
/
hiddenapi
-
force
-
blacklist.txt
Ldalvik
/
system
/
VMRuntime;
-
>setHiddenApiExemptions([Ljava
/
lang
/
String;)V
Ldalvik
/
system
/
VMRuntime;
-
>setTargetSdkVersion(I)V
Ldalvik
/
system
/
VMRuntime;
-
>setTargetSdkVersionNative(I)V
Ljava
/
lang
/
invoke
/
MethodHandles$Lookup;
-
>IMPL_LOOKUP:Ljava
/
lang
/
invoke
/
MethodHandles$Lookup;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>acquireFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndExchange([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndExchangeAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndExchangeRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndSet([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>fullFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>get([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndAdd([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndAddAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndAddRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseAnd([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseAndAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseAndRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseOr([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseOrAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseOrRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseXor([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseXorAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseXorRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndSet([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndSetAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndSetRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getOpaque([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getVolatile([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>loadLoadFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>releaseFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>
set
([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>setOpaque([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>setRelease([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>setVolatile([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>storeStoreFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSet([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSetAcquire([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSetPlain([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSetRelease([Ljava
/
lang
/
Object
;)Z
/
/
android
-
11.0
.
0_r36
liuzhuangzhuang@virtualbox:~
/
work
/
aosp
/
frameworks
/
base$
liuzhuangzhuang@virtualbox:~
/
work
/
aosp
/
frameworks
/
base$ vim config
/
hiddenapi
-
force
-
blacklist.txt
Ldalvik
/
system
/
VMRuntime;
-
>setHiddenApiExemptions([Ljava
/
lang
/
String;)V
Ldalvik
/
system
/
VMRuntime;
-
>setTargetSdkVersion(I)V
Ldalvik
/
system
/
VMRuntime;
-
>setTargetSdkVersionNative(I)V
Ljava
/
lang
/
invoke
/
MethodHandles$Lookup;
-
>IMPL_LOOKUP:Ljava
/
lang
/
invoke
/
MethodHandles$Lookup;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>acquireFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndExchange([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndExchangeAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndExchangeRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>compareAndSet([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>fullFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>get([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndAdd([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndAddAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndAddRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseAnd([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseAndAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseAndRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseOr([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseOrAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseOrRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseXor([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseXorAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndBitwiseXorRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndSet([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndSetAcquire([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getAndSetRelease([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getOpaque([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>getVolatile([Ljava
/
lang
/
Object
;)Ljava
/
lang
/
Object
;
Ljava
/
lang
/
invoke
/
VarHandle;
-
>loadLoadFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>releaseFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>
set
([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>setOpaque([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>setRelease([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>setVolatile([Ljava
/
lang
/
Object
;)V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>storeStoreFence()V
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSet([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSetAcquire([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSetPlain([Ljava
/
lang
/
Object
;)Z
Ljava
/
lang
/
invoke
/
VarHandle;
-
>weakCompareAndSetRelease([Ljava
/
lang
/
Object
;)Z
try
{
Class runtimeClass
=
Class.forName(
"dalvik.system.VMRuntime"
);
Method nativeLoadMethod
=
runtimeClass.getDeclaredMethod(
"setTargetSdkVersionNative"
,
new Class[] {
int
.
class
});
Log.d(
"whulzz"
,
"setTargetSdkVersionNative success!"
);
} catch (Exception e) {
e.printStackTrace();
}
try
{
Class runtimeClass
=
Class.forName(
"dalvik.system.VMRuntime"
);
Method nativeLoadMethod
=
runtimeClass.getDeclaredMethod(
"setTargetSdkVersionNative"
,
new Class[] {
int
.
class
});
Log.d(
"whulzz"
,
"setTargetSdkVersionNative success!"
);
} catch (Exception e) {
e.printStackTrace();
}
08
-
16
12
:
57
:
13.379
21326
21326
W System.err: java.lang.NoSuchMethodException: dalvik.system.VMRuntime.setTargetSdkVersionNative [
int
]
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at java.lang.Class.getMethod(Class.java:
2072
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at java.lang.Class.getDeclaredMethod(Class.java:
2050
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at com.example.demo.test.ApiFakeTest.fakeHiddenAPiTest(ApiFakeTest.java:
17
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at com.example.demo.DemoApplication.onCreate(DemoApplication.java:
26
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:
1190
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:
6584
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread.access$
1400
(ActivityThread.java:
226
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:
1889
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.os.Handler.dispatchMessage(Handler.java:
107
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.os.Looper.loop(Looper.java:
225
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread.main(ActivityThread.java:
7564
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at java.lang.reflect.Method.invoke(Native Method)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:
539
)
08
-
16
12
:
57
:
13.381
21326
21326
W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:
950
)
08
-
16
12
:
57
:
13.379
21326
21326
W System.err: java.lang.NoSuchMethodException: dalvik.system.VMRuntime.setTargetSdkVersionNative [
int
]
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at java.lang.Class.getMethod(Class.java:
2072
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at java.lang.Class.getDeclaredMethod(Class.java:
2050
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at com.example.demo.test.ApiFakeTest.fakeHiddenAPiTest(ApiFakeTest.java:
17
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at com.example.demo.DemoApplication.onCreate(DemoApplication.java:
26
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:
1190
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:
6584
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread.access$
1400
(ActivityThread.java:
226
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:
1889
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.os.Handler.dispatchMessage(Handler.java:
107
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.os.Looper.loop(Looper.java:
225
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at android.app.ActivityThread.main(ActivityThread.java:
7564
)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at java.lang.reflect.Method.invoke(Native Method)
08
-
16
12
:
57
:
13.380
21326
21326
W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:
539
)
08
-
16
12
:
57
:
13.381
21326
21326
W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:
950
)
|
本文 |
Free reflection |
setHiddenApiExemptions |
是 |
是 |
dex放到bootclasspath |
否 |
是 |
元反射 |
否 |
是 |
兼容安卓11 |
是 |
不太清楚 |
第三方ROM兼容性得分 |
优秀 |
良好 |
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return
getMethod(name, parameterTypes, false);
}
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
return
getMethod(name, parameterTypes, false);
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
throws NoSuchMethodException {
if
(name
=
=
null) {
throw new NullPointerException(
"name == null"
);
}
if
(parameterTypes
=
=
null) {
parameterTypes
=
EmptyArray.CLASS;
}
for
(Class<?> c : parameterTypes) {
if
(c
=
=
null) {
throw new NoSuchMethodException(
"parameter type is null"
);
}
}
Method result
=
recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
: getDeclaredMethodInternal(name, parameterTypes);
/
/
Fail
if
we didn't find the method
or
it was expected to be public.
if
(result
=
=
null ||
(recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
throw new NoSuchMethodException(getName()
+
"."
+
name
+
" "
+
Arrays.toString(parameterTypes));
}
return
result;
}
private Method getMethod(String name, Class<?>[] parameterTypes, boolean recursivePublicMethods)
throws NoSuchMethodException {
if
(name
=
=
null) {
throw new NullPointerException(
"name == null"
);
}
if
(parameterTypes
=
=
null) {
parameterTypes
=
EmptyArray.CLASS;
}
for
(Class<?> c : parameterTypes) {
if
(c
=
=
null) {
throw new NoSuchMethodException(
"parameter type is null"
);
}
}
Method result
=
recursivePublicMethods ? getPublicMethodRecursive(name, parameterTypes)
: getDeclaredMethodInternal(name, parameterTypes);
/
/
Fail
if
we didn't find the method
or
it was expected to be public.
if
(result
=
=
null ||
(recursivePublicMethods && !Modifier.isPublic(result.getAccessFlags()))) {
throw new NoSuchMethodException(getName()
+
"."
+
name
+
" "
+
Arrays.toString(parameterTypes));
}
return
result;
}
@FastNative
private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
@FastNative
private native Method getDeclaredMethodInternal(String name, Class<?>[] args);
liuzhuangzhuang.das@virtualbox:~
/
work
/
aosp
/
art
/
runtime
/
native$ ls
dalvik_system_BaseDexClassLoader.cc java_lang_Object.cc java_lang_reflect_Proxy.cc java_util_concurrent_atomic_AtomicLong.cc
dalvik_system_BaseDexClassLoader.h java_lang_Object.h java_lang_reflect_Proxy.h java_util_concurrent_atomic_AtomicLong.h
dalvik_system_DexFile.cc java_lang_ref_FinalizerReference.cc java_lang_ref_Reference.cc libcore_util_CharsetUtils.cc
dalvik_system_DexFile.h java_lang_ref_FinalizerReference.h java_lang_ref_Reference.h libcore_util_CharsetUtils.h
dalvik_system_VMDebug.cc java_lang_reflect_Array.cc java_lang_String.cc native_util.h
dalvik_system_VMDebug.h java_lang_reflect_Array.h java_lang_StringFactory.cc org_apache_harmony_dalvik_ddmc_DdmServer.cc
dalvik_system_VMRuntime.cc java_lang_reflect_Constructor.cc java_lang_StringFactory.h org_apache_harmony_dalvik_ddmc_DdmServer.h
dalvik_system_VMRuntime.h java_lang_reflect_Constructor.h java_lang_String.h org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
dalvik_system_VMStack.cc java_lang_reflect_Executable.cc java_lang_System.cc org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
dalvik_system_VMStack.h java_lang_reflect_Executable.h java_lang_System.h scoped_fast_native_object_access.h
dalvik_system_ZygoteHooks.cc java_lang_reflect_Field.cc java_lang_Thread.cc scoped_fast_native_object_access
-
inl.h
dalvik_system_ZygoteHooks.h java_lang_reflect_Field.h java_lang_Thread.h sun_misc_Unsafe.cc
java_lang_Class.cc java_lang_reflect_Method.cc java_lang_Throwable.cc sun_misc_Unsafe.h
java_lang_Class.h java_lang_reflect_Method.h java_lang_Throwable.h
java_lang_invoke_MethodHandleImpl.cc java_lang_reflect_Parameter.cc java_lang_VMClassLoader.cc
java_lang_invoke_MethodHandleImpl.h java_lang_reflect_Parameter.h java_lang_VMClassLoader.h
liuzhuangzhuang.das@virtualbox:~
/
work
/
aosp
/
art
/
runtime
/
native$ ls
dalvik_system_BaseDexClassLoader.cc java_lang_Object.cc java_lang_reflect_Proxy.cc java_util_concurrent_atomic_AtomicLong.cc
dalvik_system_BaseDexClassLoader.h java_lang_Object.h java_lang_reflect_Proxy.h java_util_concurrent_atomic_AtomicLong.h
dalvik_system_DexFile.cc java_lang_ref_FinalizerReference.cc java_lang_ref_Reference.cc libcore_util_CharsetUtils.cc
dalvik_system_DexFile.h java_lang_ref_FinalizerReference.h java_lang_ref_Reference.h libcore_util_CharsetUtils.h
dalvik_system_VMDebug.cc java_lang_reflect_Array.cc java_lang_String.cc native_util.h
dalvik_system_VMDebug.h java_lang_reflect_Array.h java_lang_StringFactory.cc org_apache_harmony_dalvik_ddmc_DdmServer.cc
dalvik_system_VMRuntime.cc java_lang_reflect_Constructor.cc java_lang_StringFactory.h org_apache_harmony_dalvik_ddmc_DdmServer.h
dalvik_system_VMRuntime.h java_lang_reflect_Constructor.h java_lang_String.h org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc
dalvik_system_VMStack.cc java_lang_reflect_Executable.cc java_lang_System.cc org_apache_harmony_dalvik_ddmc_DdmVmInternal.h
dalvik_system_VMStack.h java_lang_reflect_Executable.h java_lang_System.h scoped_fast_native_object_access.h
dalvik_system_ZygoteHooks.cc java_lang_reflect_Field.cc java_lang_Thread.cc scoped_fast_native_object_access
-
inl.h
dalvik_system_ZygoteHooks.h java_lang_reflect_Field.h java_lang_Thread.h sun_misc_Unsafe.cc
java_lang_Class.cc java_lang_reflect_Method.cc java_lang_Throwable.cc sun_misc_Unsafe.h
java_lang_Class.h java_lang_reflect_Method.h java_lang_Throwable.h
java_lang_invoke_MethodHandleImpl.cc java_lang_reflect_Parameter.cc java_lang_VMClassLoader.cc
java_lang_invoke_MethodHandleImpl.h java_lang_reflect_Parameter.h java_lang_VMClassLoader.h
static jobject Class_getDeclaredMethodInternal(JNIEnv
*
env, jobject javaThis,
jstring name, jobjectArray args) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<
1
> hs(soa.Self());
DCHECK_EQ(Runtime::Current()
-
>GetClassLinker()
-
>GetImagePointerSize(), kRuntimePointerSize);
DCHECK(!Runtime::Current()
-
>IsActiveTransaction());
ObjPtr<mirror::Class> klass
=
DecodeClass(soa, javaThis);
/
*
1.
获取
class
.
*
/
if
(UNLIKELY(klass
-
>IsObsoleteObject())) {
ThrowRuntimeException(
"Obsolete Object!"
);
return
nullptr;
}
Handle<mirror::Method> result
=
hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
/
*
2.
调用GetDeclaredMethodInternal
*
/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));
/
*
3.hiddenapi
访问上下文
*
/
if
(result
=
=
nullptr || ShouldDenyAccessToMember(result
-
>GetArtMethod(), soa.Self())) {
return
nullptr;
}
return
soa.AddLocalReference<jobject>(result.Get());
}
static jobject Class_getDeclaredMethodInternal(JNIEnv
*
env, jobject javaThis,
jstring name, jobjectArray args) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<
1
> hs(soa.Self());
DCHECK_EQ(Runtime::Current()
-
>GetClassLinker()
-
>GetImagePointerSize(), kRuntimePointerSize);
DCHECK(!Runtime::Current()
-
>IsActiveTransaction());
ObjPtr<mirror::Class> klass
=
DecodeClass(soa, javaThis);
/
*
1.
获取
class
.
*
/
if
(UNLIKELY(klass
-
>IsObsoleteObject())) {
ThrowRuntimeException(
"Obsolete Object!"
);
return
nullptr;
}
Handle<mirror::Method> result
=
hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
/
*
2.
调用GetDeclaredMethodInternal
*
/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));
/
*
3.hiddenapi
访问上下文
*
/
if
(result
=
=
nullptr || ShouldDenyAccessToMember(result
-
>GetArtMethod(), soa.Self())) {
return
nullptr;
}
return
soa.AddLocalReference<jobject>(result.Get());
}
vim art
/
runtime
/
/
mirror
/
class
.cc
template <PointerSize kPointerSize,
bool
kTransactionActive>
ObjPtr<Method> Class::GetDeclaredMethodInternal(
Thread
*
self
,
ObjPtr<Class> klass,
ObjPtr<String> name,
ObjPtr<ObjectArray<Class>> args,
const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
/
/
Covariant
return
types (
or
smali) permit the
class
to define
/
/
multiple methods with the same name
and
parameter types.
/
/
Prefer (
in
decreasing order of importance):
/
/
1
) non
-
hidden method over hidden
/
/
2
) virtual methods over direct
/
/
3
) non
-
synthetic methods over synthetic
/
/
We never
return
miranda methods that were synthesized by the runtime.
StackHandleScope<
3
> hs(
self
);
auto h_method_name
=
hs.NewHandle(name);
if
(UNLIKELY(h_method_name
=
=
nullptr)) {
ThrowNullPointerException(
"name == null"
);
return
nullptr;
}
auto h_args
=
hs.NewHandle(args);
Handle<Class> h_klass
=
hs.NewHandle(klass);
constexpr hiddenapi::AccessMethod access_method
=
hiddenapi::AccessMethod::kNone;
ArtMethod
*
result
=
nullptr;
bool
result_hidden
=
false;
for
(auto& m : h_klass
-
>GetDeclaredVirtualMethods(kPointerSize)) {
/
*
4.
遍历virtual method
*
/
if
(m.IsMiranda()) {
continue
;
}
auto
*
np_method
=
m.GetInterfaceMethodIfProxy(kPointerSize);
/
/
May cause thread suspension.
ObjPtr<String> np_name
=
np_method
-
>ResolveNameString();
if
(!np_name
-
>Equals(h_method_name.Get()) || !np_method
-
>EqualParameters(h_args)) {
/
*
5.
判断方法名与参数类型
*
/
if
(UNLIKELY(
self
-
>IsExceptionPending())) {
return
nullptr;
}
continue
;
}
bool
m_hidden
=
hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
/
*
6.
调用ShouldDenyAccessToMember
*
/
if
(!m_hidden && !m.IsSynthetic()) {
/
/
Non
-
hidden, virtual, non
-
synthetic. Best possible result, exit early.
return
Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(
self
, &m);
}
else
if
(IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
/
/
Remember as potential result.
result
=
&m;
result_hidden
=
m_hidden;
}
}
if
((result !
=
nullptr) && !result_hidden) {
/
/
We have
not
found a non
-
hidden, virtual, non
-
synthetic method, but
/
/
if
we have found a non
-
hidden, virtual, synthetic method, we cannot
/
/
do better than that later.
DCHECK(!result
-
>IsDirect());
DCHECK(result
-
>IsSynthetic());
}
else
{
for
(auto& m : h_klass
-
>GetDirectMethods(kPointerSize)) {
/
*
7.
遍历direct method
*
/
auto modifiers
=
m.GetAccessFlags();
if
((modifiers & kAccConstructor) !
=
0
) {
continue
;
}
auto
*
np_method
=
m.GetInterfaceMethodIfProxy(kPointerSize);
/
/
May cause thread suspension.
ObjPtr<String> np_name
=
np_method
-
>ResolveNameString();
if
(np_name
=
=
nullptr) {
self
-
>AssertPendingException();
return
nullptr;
}
if
(!np_name
-
>Equals(h_method_name.Get()) || !np_method
-
>EqualParameters(h_args)) {
/
*
8.
判断方法名与参数类型
*
/
if
(UNLIKELY(
self
-
>IsExceptionPending())) {
return
nullptr;
}
continue
;
}
DCHECK(!m.IsMiranda());
/
/
Direct methods cannot be miranda methods.
bool
m_hidden
=
hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
/
*
9.
调用ShouldDenyAccessToMember
*
/
if
(!m_hidden && !m.IsSynthetic()) {
/
/
Non
-
hidden, direct, non
-
synthetic.
Any
virtual result could only have been
/
/
hidden, therefore this
is
the best possible match. Exit now.
DCHECK((result
=
=
nullptr) || result_hidden);
return
Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(
self
, &m);
}
else
if
(IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
/
/
Remember as potential result.
result
=
&m;
result_hidden
=
m_hidden;
}
}
}
return
result !
=
nullptr
? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(
self
, result)
: nullptr;
}
vim art
/
runtime
/
/
mirror
/
class
.cc
template <PointerSize kPointerSize,
bool
kTransactionActive>
ObjPtr<Method> Class::GetDeclaredMethodInternal(
Thread
*
self
,
ObjPtr<Class> klass,
ObjPtr<String> name,
ObjPtr<ObjectArray<Class>> args,
const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
/
/
Covariant
return
types (
or
smali) permit the
class
to define
/
/
multiple methods with the same name
and
parameter types.
/
/
Prefer (
in
decreasing order of importance):
/
/
1
) non
-
hidden method over hidden
/
/
2
) virtual methods over direct
/
/
3
) non
-
synthetic methods over synthetic
/
/
We never
return
miranda methods that were synthesized by the runtime.
StackHandleScope<
3
> hs(
self
);
auto h_method_name
=
hs.NewHandle(name);
if
(UNLIKELY(h_method_name
=
=
nullptr)) {
ThrowNullPointerException(
"name == null"
);
return
nullptr;
}
auto h_args
=
hs.NewHandle(args);
Handle<Class> h_klass
=
hs.NewHandle(klass);
constexpr hiddenapi::AccessMethod access_method
=
hiddenapi::AccessMethod::kNone;
ArtMethod
*
result
=
nullptr;
bool
result_hidden
=
false;
for
(auto& m : h_klass
-
>GetDeclaredVirtualMethods(kPointerSize)) {
/
*
4.
遍历virtual method
*
/
if
(m.IsMiranda()) {
continue
;
}
auto
*
np_method
=
m.GetInterfaceMethodIfProxy(kPointerSize);
/
/
May cause thread suspension.
ObjPtr<String> np_name
=
np_method
-
>ResolveNameString();
if
(!np_name
-
>Equals(h_method_name.Get()) || !np_method
-
>EqualParameters(h_args)) {
/
*
5.
判断方法名与参数类型
*
/
if
(UNLIKELY(
self
-
>IsExceptionPending())) {
return
nullptr;
}
continue
;
}
bool
m_hidden
=
hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
/
*
6.
调用ShouldDenyAccessToMember
*
/
if
(!m_hidden && !m.IsSynthetic()) {
/
/
Non
-
hidden, virtual, non
-
synthetic. Best possible result, exit early.
return
Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(
self
, &m);
}
else
if
(IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
/
/
Remember as potential result.
result
=
&m;
result_hidden
=
m_hidden;
}
}
if
((result !
=
nullptr) && !result_hidden) {
/
/
We have
not
found a non
-
hidden, virtual, non
-
synthetic method, but
/
/
if
we have found a non
-
hidden, virtual, synthetic method, we cannot
/
/
do better than that later.
DCHECK(!result
-
>IsDirect());
DCHECK(result
-
>IsSynthetic());
}
else
{
for
(auto& m : h_klass
-
>GetDirectMethods(kPointerSize)) {
/
*
7.
遍历direct method
*
/
auto modifiers
=
m.GetAccessFlags();
if
((modifiers & kAccConstructor) !
=
0
) {
continue
;
}
auto
*
np_method
=
m.GetInterfaceMethodIfProxy(kPointerSize);
/
/
May cause thread suspension.
ObjPtr<String> np_name
=
np_method
-
>ResolveNameString();
if
(np_name
=
=
nullptr) {
self
-
>AssertPendingException();
return
nullptr;
}
if
(!np_name
-
>Equals(h_method_name.Get()) || !np_method
-
>EqualParameters(h_args)) {
/
*
8.
判断方法名与参数类型
*
/
if
(UNLIKELY(
self
-
>IsExceptionPending())) {
return
nullptr;
}
continue
;
}
DCHECK(!m.IsMiranda());
/
/
Direct methods cannot be miranda methods.
bool
m_hidden
=
hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
/
*
9.
调用ShouldDenyAccessToMember
*
/
if
(!m_hidden && !m.IsSynthetic()) {
/
/
Non
-
hidden, direct, non
-
synthetic.
Any
virtual result could only have been
/
/
hidden, therefore this
is
the best possible match. Exit now.
DCHECK((result
=
=
nullptr) || result_hidden);
return
Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(
self
, &m);
}
else
if
(IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
/
/
Remember as potential result.
result
=
&m;
result_hidden
=
m_hidden;
}
}
}
return
result !
=
nullptr
? Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(
self
, result)
: nullptr;
}
template<typename T>
inline
bool
ShouldDenyAccessToMember(T
*
member,
const std::function<AccessContext()>& fn_get_access_context,
AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(member !
=
nullptr);
/
/
Get the runtime flags encoded
in
member's access flags.
/
/
Note: this works
for
proxy methods because they inherit access flags
from
their
/
/
respective interface methods.
const uint32_t runtime_flags
=
GetRuntimeFlags(member);
/
/
Exit early
if
member
is
public API. This flag
is
also
set
for
non
-
boot
class
/
/
path fields
/
methods.
if
((runtime_flags & kAccPublicApi) !
=
0
) {
/
*
1.
如果方法是public api,则允许访问
*
/
return
false;
}
/
/
Determine which domain the caller
and
callee belong to.
/
/
This can be
*
very
*
expensive. This
is
why ShouldDenyAccessToMember
/
/
should
not
be called on every individual access.
const AccessContext caller_context
=
fn_get_access_context();
/
*
2.
获取caller的上下文
*
/
const AccessContext callee_context(member
-
>GetDeclaringClass());
/
*
3.
获取所调用方法的上下文
*
/
/
/
Non
-
boot classpath callers should have exited early.
DCHECK(!callee_context.IsApplicationDomain());
/
/
Check
if
the caller
is
always allowed to access members
in
the callee context.
if
(caller_context.CanAlwaysAccess(callee_context)) {
/
*
4.caller
是否可以不受约束访问callee
*
/
return
false;
}
/
/
Check
if
this
is
platform accessing core platform. We may warn
if
`member`
is
/
/
not
part of core platform API.
/
*
5.
根据domain级别区分对待hiddenapi策略
*
/
switch (caller_context.GetDomain()) {
case Domain::kApplication: {
DCHECK(!callee_context.IsApplicationDomain());
/
/
Exit early
if
access checks are completely disabled.
EnforcementPolicy policy
=
Runtime::Current()
-
>GetHiddenApiEnforcementPolicy();
if
(policy
=
=
EnforcementPolicy::kDisabled) {
/
*
5.1
.如果policydisable,则返回false,即允许访问
*
/
return
false;
}
/
/
If this
is
a proxy method, look at the interface method instead.
member
=
detail::GetInterfaceMemberIfProxy(member);
/
/
Decode hidden API access flags
from
the dex
file
.
/
/
This
is
an O(N) operation scaling with the number of fields
/
methods
/
/
in
the
class
. Only do this on slow path
and
only do it once.
ApiList api_list(detail::GetDexFlags(member));
DCHECK(api_list.IsValid());
/
/
Member
is
hidden
and
caller
is
not
exempted. Enter slow path.
return
detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
}
case Domain::kPlatform: {
DCHECK(callee_context.GetDomain()
=
=
Domain::kCorePlatform);
/
/
Member
is
part of core platform API. Accessing it
is
allowed.
if
((runtime_flags & kAccCorePlatformApi) !
=
0
) {
return
false;
}
/
/
Allow access
if
access checks are disabled.
EnforcementPolicy policy
=
Runtime::Current()
-
>GetCorePlatformApiEnforcementPolicy();
if
(policy
=
=
EnforcementPolicy::kDisabled) {
return
false;
}
/
/
If this
is
a proxy method, look at the interface method instead.
member
=
detail::GetInterfaceMemberIfProxy(member);
/
/
Access checks are
not
disabled, report the violation.
/
/
This may also add kAccCorePlatformApi to the access flags of `member`
/
/
so as to
not
warn again on
next
access.
return
detail::HandleCorePlatformApiViolation(member,
caller_context,
access_method,
policy);
}
case Domain::kCorePlatform: {
LOG(FATAL) <<
"CorePlatform domain should be allowed to access all domains"
;
UNREACHABLE();
}
}
}
template<typename T>
inline
bool
ShouldDenyAccessToMember(T
*
member,
const std::function<AccessContext()>& fn_get_access_context,
AccessMethod access_method)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(member !
=
nullptr);
/
/
Get the runtime flags encoded
in
member's access flags.
/
/
Note: this works
for
proxy methods because they inherit access flags
from
their
/
/
respective interface methods.
const uint32_t runtime_flags
=
GetRuntimeFlags(member);
/
/
Exit early
if
member
is
public API. This flag
is
also
set
for
non
-
boot
class
/
/
path fields
/
methods.
if
((runtime_flags & kAccPublicApi) !
=
0
) {
/
*
1.
如果方法是public api,则允许访问
*
/
return
false;
}
/
/
Determine which domain the caller
and
callee belong to.
/
/
This can be
*
very
*
expensive. This
is
why ShouldDenyAccessToMember
/
/
should
not
be called on every individual access.
const AccessContext caller_context
=
fn_get_access_context();
/
*
2.
获取caller的上下文
*
/
const AccessContext callee_context(member
-
>GetDeclaringClass());
/
*
3.
获取所调用方法的上下文
*
/
/
/
Non
-
boot classpath callers should have exited early.
DCHECK(!callee_context.IsApplicationDomain());
/
/
Check
if
the caller
is
always allowed to access members
in
the callee context.
if
(caller_context.CanAlwaysAccess(callee_context)) {
/
*
4.caller
是否可以不受约束访问callee
*
/
return
false;
}
/
/
Check
if
this
is
platform accessing core platform. We may warn
if
`member`
is
/
/
not
part of core platform API.
/
*
5.
根据domain级别区分对待hiddenapi策略
*
/
switch (caller_context.GetDomain()) {
case Domain::kApplication: {
DCHECK(!callee_context.IsApplicationDomain());
/
/
Exit early
if
access checks are completely disabled.
EnforcementPolicy policy
=
Runtime::Current()
-
>GetHiddenApiEnforcementPolicy();
if
(policy
=
=
EnforcementPolicy::kDisabled) {
/
*
5.1
.如果policydisable,则返回false,即允许访问
*
/
return
false;
}
/
/
If this
is
a proxy method, look at the interface method instead.
member
=
detail::GetInterfaceMemberIfProxy(member);
/
/
Decode hidden API access flags
from
the dex
file
.
/
/
This
is
an O(N) operation scaling with the number of fields
/
methods
/
/
in
the
class
. Only do this on slow path
and
only do it once.
ApiList api_list(detail::GetDexFlags(member));
DCHECK(api_list.IsValid());
/
/
Member
is
hidden
and
caller
is
not
exempted. Enter slow path.
return
detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
}
case Domain::kPlatform: {
DCHECK(callee_context.GetDomain()
=
=
Domain::kCorePlatform);
/
/
Member
is
part of core platform API. Accessing it
is
allowed.
if
((runtime_flags & kAccCorePlatformApi) !
=
0
) {
return
false;
}
/
/
Allow access
if
access checks are disabled.
EnforcementPolicy policy
=
Runtime::Current()
-
>GetCorePlatformApiEnforcementPolicy();
if
(policy
=
=
EnforcementPolicy::kDisabled) {
return
false;
}
/
/
If this
is
a proxy method, look at the interface method instead.
member
=
detail::GetInterfaceMemberIfProxy(member);
/
/
Access checks are
not
disabled, report the violation.
/
/
This may also add kAccCorePlatformApi to the access flags of `member`
/
/
so as to
not
warn again on
next
access.
return
detail::HandleCorePlatformApiViolation(member,
caller_context,
access_method,
policy);
}
case Domain::kCorePlatform: {
LOG(FATAL) <<
"CorePlatform domain should be allowed to access all domains"
;
UNREACHABLE();
}
}
}
/
/
java_lang_Class.cc
Handle<mirror::Method> result
=
hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
/
*
2.
调用GetDeclaredMethodInternal
*
/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));
/
*
3.hiddenapi
访问上下文
*
/
/
/
java_lang_Class.cc
Handle<mirror::Method> result
=
hs.NewHandle(
mirror::Class::GetDeclaredMethodInternal<kRuntimePointerSize, false>(
/
*
2.
调用GetDeclaredMethodInternal
*
/
soa.Self(),
klass,
soa.Decode<mirror::String>(name),
soa.Decode<mirror::ObjectArray<mirror::Class>>(args),
GetHiddenapiAccessContextFunction(soa.Self())));
/
*
3.hiddenapi
访问上下文
*
/
/
/
java_lang_Class.cc
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread
*
self
) {
return
[
=
]() REQUIRES_SHARED(Locks::mutator_lock_) {
return
GetReflectionCaller(
self
); };
}
/
/
java_lang_Class.cc
static std::function<hiddenapi::AccessContext()> GetHiddenapiAccessContextFunction(Thread
*
self
) {
return
[
=
]() REQUIRES_SHARED(Locks::mutator_lock_) {
return
GetReflectionCaller(
self
); };
}
if
((runtime_flags & kAccPublicApi) !
=
0
) {
/
*
1.
如果方法是public api,则允许访问
*
/
return
false;
}
if
((runtime_flags & kAccPublicApi) !
=
0
) {
/
*
1.
如果方法是public api,则允许访问
*
/
return
false;
}
const AccessContext caller_context
=
fn_get_access_context();
/
*
2.
获取caller的上下文
*
/
const AccessContext caller_context
=
fn_get_access_context();
/
*
2.
获取caller的上下文
*
/
const AccessContext callee_context(member
-
>GetDeclaringClass());
/
*
3.
获取所调用方法的上下文
*
/
const AccessContext callee_context(member
-
>GetDeclaringClass());
/
*
3.
获取所调用方法的上下文
*
/
/
/
Check
if
the caller
is
always allowed to access members
in
the callee context.
if
(caller_context.CanAlwaysAccess(callee_context)) {
/
*
4.caller
是否可以不受约束访问callee
*
/
return
false;
}
/
/
Check
if
the caller
is
always allowed to access members
in
the callee context.
if
(caller_context.CanAlwaysAccess(callee_context)) {
/
*
4.caller
是否可以不受约束访问callee
*
/
return
false;
}
/
/
hidden_api.h
/
/
Returns true
if
this domain
is
always allowed to access the domain of `callee`.
bool
CanAlwaysAccess(const AccessContext& callee) const {
return
IsDomainMoreTrustedThan(domain_, callee.domain_);
}
/
/
hidden_api.h
/
/
Returns true
if
this domain
is
always allowed to access the domain of `callee`.
bool
CanAlwaysAccess(const AccessContext& callee) const {
return
IsDomainMoreTrustedThan(domain_, callee.domain_);
}
/
/
art
/
libartbase
/
base
/
hiddenapi_domain.h
enum
class
Domain : char {
kCorePlatform
=
0
,
kPlatform,
kApplication,
};
inline
bool
IsDomainMoreTrustedThan(Domain domainA, Domain domainB) {
return
static_cast<char>(domainA) <
=
static_cast<char>(domainB);
}
/
/
art
/
libartbase
/
base
/
hiddenapi_domain.h
enum
class
Domain : char {
kCorePlatform
=
0
,
kPlatform,
kApplication,
};
inline
bool
IsDomainMoreTrustedThan(Domain domainA, Domain domainB) {
return
static_cast<char>(domainA) <
=
static_cast<char>(domainB);
}
template<typename T>
bool
ShouldDenyAccessToMemberImpl(T
*
member, ApiList api_list, AccessMethod access_method) {
DCHECK(member !
=
nullptr);
Runtime
*
runtime
=
Runtime::Current();
EnforcementPolicy hiddenApiPolicy
=
runtime
-
>GetHiddenApiEnforcementPolicy();
DCHECK(hiddenApiPolicy !
=
EnforcementPolicy::kDisabled)
<<
"Should never enter this function when access checks are completely disabled"
;
MemberSignature member_signature(member);
/
/
Check
for
an exemption first. Exempted APIs are treated as white
list
.
if
(member_signature.DoesPrefixMatchAny(runtime
-
>GetHiddenApiExemptions())) {
/
/
Avoid re
-
examining the exemption
list
next
time.
/
/
Note this results
in
no warning
for
the member, which seems like what one would expect.
/
/
Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return
false;
}
.....
省略
....
template<typename T>
bool
ShouldDenyAccessToMemberImpl(T
*
member, ApiList api_list, AccessMethod access_method) {
DCHECK(member !
=
nullptr);
Runtime
*
runtime
=
Runtime::Current();
EnforcementPolicy hiddenApiPolicy
=
runtime
-
>GetHiddenApiEnforcementPolicy();
DCHECK(hiddenApiPolicy !
=
EnforcementPolicy::kDisabled)
<<
"Should never enter this function when access checks are completely disabled"
;
MemberSignature member_signature(member);
/
/
Check
for
an exemption first. Exempted APIs are treated as white
list
.
if
(member_signature.DoesPrefixMatchAny(runtime
-
>GetHiddenApiExemptions())) {
/
/
Avoid re
-
examining the exemption
list
next
time.
/
/
Note this results
in
no warning
for
the member, which seems like what one would expect.
/
/
Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return
false;
}
.....
省略
....
EnforcementPolicy policy
=
Runtime::Current()
-
>GetHiddenApiEnforcementPolicy();
if
(policy
=
=
EnforcementPolicy::kDisabled) {
/
*
5.1
.如果policydisable,则返回false,即允许访问
*
/
return
false;
}
EnforcementPolicy policy
=
Runtime::Current()
-
>GetHiddenApiEnforcementPolicy();
if
(policy
=
=
EnforcementPolicy::kDisabled) {
/
*
5.1
.如果policydisable,则返回false,即允许访问
*
/
return
false;
}
hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const {
return
hidden_api_policy_;
}
hiddenapi::EnforcementPolicy GetHiddenApiEnforcementPolicy() const {
return
hidden_api_policy_;
}
/
/
Check
for
an exemption first. Exempted APIs are treated as white
list
.
if
(member_signature.DoesPrefixMatchAny(runtime
-
>GetHiddenApiExemptions())) {
/
/
Avoid re
-
examining the exemption
list
next
time.
/
/
Note this results
in
no warning
for
the member, which seems like what one would expect.
/
/
Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return
false;
}
/
/
Check
for
an exemption first. Exempted APIs are treated as white
list
.
if
(member_signature.DoesPrefixMatchAny(runtime
-
>GetHiddenApiExemptions())) {
/
/
Avoid re
-
examining the exemption
list
next
time.
/
/
Note this results
in
no warning
for
the member, which seems like what one would expect.
/
/
Exemptions effectively adds new members to the whitelist.
MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
return
false;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2021-8-16 20:53
被whulzz编辑
,原因: 添加git仓库