Android中$符号的含义?classname$a.a()空对象引用异常咨询
嘿,我来帮你把这个问题掰扯明白!
Android里$符号到底啥意思?
在Android(其实Java里也是一样的),$符号是用来标记内部类/匿名内部类的命名规则:
- 要是你看到
OuterClass$InnerClass这种格式,说明InnerClass是OuterClass的一个普通内部类(有名字的那种) - 像你日志里的
TestClass$a这种,是被Proguard混淆后的匿名内部类——Proguard会把没名字的匿名类改成a、b这种短标识,所以原代码里它应该是TestClass里定义的某个匿名内部类或者内部接口
你的空指针崩溃该怎么分析?
先看你给出的崩溃日志:
Caused by java.lang.NullPointerException: Attempt to invoke interface method 'void com.package.TestClass$a.a()' on a null object reference
简单说,就是你在调用TestClass里那个被混淆成a的内部类/接口实例的a()方法时,这个实例压根没初始化,是个null!而且崩溃的调用链是:TestClass.onStartCommand() → TestClass.a() → TestClass.h() → 触发空指针。
没了Proguard映射文件,怎么排查?
虽然映射文件被覆盖了,也不是完全没办法:
- 先直奔
TestClass的onStartCommand()方法,顺着调用链找a()和h()方法,看看里面用到了哪些内部类实例 - 重点检查那些在
h()方法里调用的内部类对象,是不是有可能在初始化完成前就被调用了?比如是不是异步加载的对象还没返回就去调用它的方法? - 回忆下最近对
TestClass的修改:有没有新增匿名内部类,或者改了内部类实例的初始化逻辑? - 可以临时在测试环境关闭Proguard,重新跑一遍复现崩溃,这样就能看到真实的类名和方法名,定位起来会轻松很多
给你提个醒
以后每次用Proguard构建发布版本时,一定要记得备份app/build/outputs/mapping/release/目录下的映射文件,把它和对应的APK一起存好,这样之后遇到崩溃日志,就能直接反混淆成真实的代码位置,不用像现在这么头疼啦!
内容的提问来源于stack exchange,提问作者Rahul Rawat
相关产品推荐
相关产品推荐

