V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nnegier
V2EX  ›  Android

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

  •  1
     
  •   nnegier · 2022-01-04 16:39:19 +08:00 · 4328 次点击
    这是一个创建于 815 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码:

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

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

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

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

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

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

    真的很气人。

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

    Jooooooooo
        1
    Jooooooooo  
       2022-01-04 16:42:52 +08:00
    是不是引的包有冲突.
    xia0pia0
        2
    xia0pia0  
       2022-01-04 16:51:10 +08:00
    Method method = object.getClass().getDeclaredMethod(methodName);
    method.setAccessible(true);
    Object r = method.invoke(object);

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

    另外我不太确定是不是内联的原因是,私有方法确实都没了。如果是仅仅被一次使用的私有方法没有出现,那被内联的可能性还是很大的,但是我看还有挺多是多处被使用的私有方法。
    lxxself
        17
    lxxself  
       2022-01-04 19:53:45 +08:00
    蹲一个结果
    yiranshaxiao
        18
    yiranshaxiao  
       2022-01-04 22:00:00 +08:00
    Accessing hidden method Landroid/widget/NumberPicker;->validateInputTextView(Landroid/view/View;)V (greylist-max-o, reflection, denied)
    nnegier
        19
    nnegier  
    OP
       2022-01-05 00:20:05 +08:00
    @essicaj 把 targetSdkVersion 设置为 28 及以上,我的问题就能复现了
    nnegier
        20
    nnegier  
    OP
       2022-01-05 00:20:36 +08:00
    @lxxself 散了吧,无解
    nnegier
        21
    nnegier  
    OP
       2022-01-05 00:21:00 +08:00
    @junas7 android 官方的限制
    nnegier
        22
    nnegier  
    OP
       2022-01-05 00:21:21 +08:00
    @yiranshaxiao 高手
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2842 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:20 · PVG 21:20 · LAX 06:20 · JFK 09:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.