个人解答:为什么源码中的断点行会错位

解答看底部 QA环节


推理过程

当我调试断点到源码时,很多时候断点行数都是错位的,网上说是因为 手机SDK 与 Studio的SDK 版本不一致。

但是我写的、编译的、运行的都是v28的代码,怎么断点会跑到v26的代码中呢?

再说了,假如我调用v28才出现的方法时,断点不可能走到v26中的,因为根本就没有那个方法。

Android手机的Android版本无法升级,固定 v26,但是我估计这个 手机v26 并不是代码的v26,正如新方法的例子,我调用了v28才有的方法,v26上不可能成功调用的。

所有App都必须依赖原生代码包,但是依赖的源码包并不是同一个版本,有的依赖 v26、v27、v28 都有依赖,那么源码包放在了哪里?

通过反编译apk得知,源码就存放在apk里,但是这里的源码并不全,真的就是我在Studio上看到的源码吗?

反编译apk得到的源码中存在AppCompatTextView,但有些细节并不同。它多了个在Studio下看不到的变量 mPrecomputedTextFuture。参与了Studio下看不到的函数 consumeTextFutureAndSetBlocking()。

由此我推断:Studio中看到的代码并不是真实运行的代码,断点的显示是将它们一一对应了起来。

再者,在Apk的源码中没有TextView、View 等这些基础类的,但是这些类是必须的。import android.widget.TextView

我猜测:这些基础类型使用的是手机中的类库,所以它没在apk中,它们是随手机系统固定不变的,旧版的Activity的的确确没有权限请求方法。

那么它是怎么跨过版本间的差异进行调用的呢?我突然想到了 @RequiresApi 注释 - 必须在指定版本以上才能使用。

最常见的权限请求 API>23,编译器会强行要求我们写出来版本辨别,而不是自己当做默认申请成功处理。这样做一定是有特别的意义。

此外,我又发现apk源码中包含 ActivityCompat,而这个 ActivityCompat 原原本本的写明了 activity.requestPermission()!

因为低版本根本没有activity.requestPermission(),这样子写明是绝对无法通过低版本的代码校验的!除非,实际运行前不需要代码校验!

为了确认这一点,回忆打包流程:.java -> .class(javac) -> .dex(android工具) -> 生成apk。

我看到的apk源码是从 dex 反编译来的,所以.dex中仍然包含activity.requestPermission。而Android实际运行.dex确实跳过了Java的代码校验!

我猜测:打包后代码不会被校验,以此来跨过方法不存在,进而编译不过的问题,实际运行时由版本号区别是否执行activity.requestPermission() 方法

 

QA解答 回想一下,我一开始的问题

Q:为什么断点在源码中会错位?
A:因为断点追踪的位置不是你编译的v28代码,而是手机里实际运行的v26代码,如果你的手机是v28的就不错位了。
Q:为什么断点追踪的行不是我依赖的、编写的v28代码,而是v26代码?
A:因为底层实际用到的、运行的是v26的代码,在android包下的代码是不会被打包进apk的,代码实际用到的是手机系统中的代码。
   此外,Studio中看到的代码并不是真实运行的代码,断点的显示是将它们一一对应了起来
Q:那如果我在API22的手机上写了API23才有的权限请求,肯定报错啊!
A:你指的报错是[编译报错],而不是[运行报错],API23的权限请求代码被打包到.dex,而.dex的编译规则不同,是不会报错的。
   至于[运行报错],编译器限制了再使用权限请求时必须API>23才行,或者通过适配类适配,是不会实际运行到权限请求的。

Q:编译器的版本限制是由最低兼容版本决定的,它会妨碍我使用新的依赖库吗?

A:普通的功能可以通过适配模式实现(Androidv4v7兼容包、兼容类),而编译器的版本限制是说在低版本上无论如何都无法实现这个功能的,比如无论如何都无法在API20的手机上将状态栏变色,因为底层还没做这个API。所以极大多数新的依赖库都可以使用,因为它并不依赖底层功能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值