nnegier
V2EX  ›  Android

为什么 android/ Java 反射无法获取到私有方法,倒是能获取到 public 的方法

  •  1
     
  •   nnegier · Jan 4, 2022 · 14616 views
    This topic created in 1767 days ago, the information mentioned may be changed or developed.

    代码:

    Method[] declaredMethods = Class.forName("android.widget.NumberPicker").getDeclaredMethods();
    for (Method method:declaredMethods) {
    	Logger.e(method.toString()); 
    }
    

    我查看了 Log ,一个 private 的方法都没有,google 百度无果,自行查询研究无果,特来求教,另外获取私有属性倒是正常的,就是私有方法不行。

    问题来源,最开始是想获取单个私有方法,就是这个 validateInputTextView 私有方法,发现报错 NoSuchMethodException ,无论怎么获取测试都是这样,所以就决定把所有方法都打印出来,结果里面一个私有方法都没有。

    Supplement 1  ·  Jan 4, 2022
    有热心的 android 开发可以复制到程序中运行看看
    Supplement 2  ·  Jan 4, 2022
    谢谢各位,得知一位朋友运行成功我才意识到了代码没有问题,随即我也在 Windows 上的 Android Studio 上运行成功。所以某种程度上我问了一个不是问题的问题,我感到很抱歉。但我出现问题的环境是 Kubuntu 上的 Android Studio ,我反复验证了,依旧失败,我平常在 Kubuntu 上开发,因为 Windows 我感觉不太稳定,动不动给我蓝屏,鉴于我之前解决过一次蓝屏,再鉴于此次事件,以及 Kubuntu 软件方面的缺乏,所以我决定要换回 Windows 开发环境了,算是自动绕开了这个问题吧。Kubuntu 我用了蛮久,也用它开发主要的项目,挺喜欢的,经此一事,咱们以后还是在虚拟机里见吧,再见。
    Supplement 3  ·  Jan 5, 2022

    不是Kubuntu的问题,这个问题是Google Android的问题,而且正因为如此无解,Google在Android 9(API 级别 28)加了限制,无法访问私有方法,当然targetSdkVersion低于28是可以的,往上就不行。

    我很气愤,它限制这个做啥?说什么提高稳定性,他就觉得要用到反射来做些事情的人是菜鸟吗,我实说我是想帮它NumberPicker优化点逻辑,细节方面不到位,我给其私有字段设置了监听器,然后还需要用到一个私有方法,于是就有了今天的问题。

    真的很气人。

    https://developer.android.com/guide/app-compatibility/restrictions-non-sdk-interfaces

    Jooooooooo
    Jooooooooo
    Jan 4, 2022
    1
    是不是引的包有冲突.
    xia0pia0
    xia0pia0
    Jan 4, 2022
    2
    Method method = object.getClass().getDeclaredMethod(methodName);
    method.setAccessible(true);
    Object r = method.invoke(object);

    SecurityManager 可能会拦截掉 setAccessible
    nnegier
    nnegier
    OP
    Jan 4, 2022
    3
    @Jooooooooo 正常运行
    nnegier
    nnegier
    OP
    Jan 4, 2022
    4
    @xia0pia0 关键是 getDeclaredMethods 里面就没有私有的方法,我全部打印出来看过了,setAccessible 、invoke 啥的都是后话了,前面就失败了
    nnegier
    nnegier
    OP
    Jan 4, 2022
    6
    @aguesuka 真实的类里有的。肯定是有的,它是私有方法,而且你看的那个链接也很能说明问题,那里展示的没有私有方法
    junas7
    junas7
    Jan 4, 2022
    7
    私有方法写在 android.widget.NumberPicker 的父类?
    picy
    picy
    Jan 4, 2022
    8
    hidden-api 限制?
    nnegier
    nnegier
    OP
    Jan 4, 2022
    9
    @junas7 不是,是自己类里定义的,我反复查过
    nnegier
    nnegier
    OP
    Jan 4, 2022
    10
    @janstk 不是,没有 hide ,关键是一个私有方法都获取不到
    yescpu
    yescpu
    Jan 4, 2022
    11
    怎么确定代码里面有?是不是 Android Studio 里面点源码里面看能看到这个方法?
    但这不意味着 App 运行的 framework 中也一定有这个方法,如果你排除 hide 了的情况的话可能的原因是定制 rom 把这个方法干掉了。
    e99unc1e
    e99unc1e
    Jan 4, 2022
    12
    我刚刚在自己设备上也试了下,MIUI12 Android 9 ,也没有这个方法,有可能是编译的时候优化掉了吗。
    codehz
    codehz
    Jan 4, 2022 via Android
    13
    你把 framework 从设备里提取出来反编译一下试试?
    essicaj
    essicaj
    PRO
    Jan 4, 2022
    14
    一个 private 的方法都没有,确实有点奇怪。我试了下我手上的 android 11 的设备,和你一样的代码是能取到 validateInputTextView 这个方法的。或许和设备有点关系?
    e99unc1e
    e99unc1e
    Jan 4, 2022
    16
    @nnegier 编译的时候可能会有部分方法被优化掉,比如内联之类的,源代码里面有不代表最终产物有。我赞成 13 楼的建议,吧 framework jar 之类的东西提取出来看看里面的情况。

    另外我不太确定是不是内联的原因是,私有方法确实都没了。如果是仅仅被一次使用的私有方法没有出现,那被内联的可能性还是很大的,但是我看还有挺多是多处被使用的私有方法。
    lxxself
    lxxself
    Jan 4, 2022
    17
    蹲一个结果
    yiranshaxiao
    yiranshaxiao
    Jan 4, 2022
    18
    Accessing hidden method Landroid/widget/NumberPicker;->validateInputTextView(Landroid/view/View;)V (greylist-max-o, reflection, denied)
    nnegier
    nnegier
    OP
    Jan 5, 2022
    19
    @essicaj 把 targetSdkVersion 设置为 28 及以上,我的问题就能复现了
    nnegier
    nnegier
    OP
    Jan 5, 2022
    20
    @lxxself 散了吧,无解
    nnegier
    nnegier
    OP
    Jan 5, 2022
    21
    @junas7 android 官方的限制
    nnegier
    nnegier
    OP
    Jan 5, 2022
    22
    @yiranshaxiao 高手
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   916 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 20:16 · PVG 04:16 · LAX 12:16 · JFK 15:16
    ♥ Do have faith in what you're doing.