前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kotlin 反射与 MetaData 的关系在混淆后浮出水面!

Kotlin 反射与 MetaData 的关系在混淆后浮出水面!

作者头像
bennyhuo
发布2020-02-20 13:24:09
1.5K0
发布2020-02-20 13:24:09
举报
文章被收录于专栏:BennyhuoBennyhuo

概要

本文主要为大家介绍 Kotlin 反射的一些原理,并提示大家如果需要在使用 Kotlin 反射的工程中进行混淆,千万注意,对所有反射涉及的类和接口的父类都需要 Keep。

问题的产生

话说我曾经遇到过一个问题,这个问题可以用下面的代码复现:

代码语言:javascript
复制
open class SuperClass

class SubClass: SuperClass(){
    companion object {
        fun seeErrorAfterProguard(){
            try {
                SubClass::class.supertypes.forEach {
                    debug(it)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

如果混淆的时候没有 keep 这两个类,那么使用 Kotlin 反射时会抛一个无法找到 SuperClass 这个类的异常。

可能有些朋友可能还没有反应过来这是什么意思,如果我们使用 Java 反射的话,哪怕 SuperClass 这个类已经被混淆成了 a,那么使用 SubClass 获取它的父类也应该是去找 a 这个类,而不会仍然回去找什么 SuperClass,毕竟这个类信息已经在混淆的时候被改了呀,运行时的 Kotlin 反射又是怎么知道它的存在的呢?

Kotlin 反射的小伎俩

Kotlin 反射能够拿到 Java 反射拿不到的很多东西,这一点毋庸置疑,毕竟 Kotlin 的语法特性更复杂,需要的信息也更多。可是,既然最后大家都编译成了字节码,如果字节码里面原来就有这些信息,Java 反射无论如何也不应该金屋藏娇,捂着不给人看吧——Kotlin 反射一定是另辟蹊径的,不然它又怎么会突破字节码的限制呢?

那么它是怎么做到的呢?当然是这个:

代码语言:javascript
复制
@Metadata(
   mv = {1, 1, 9},
   bv = {1, 0, 2},
   k = 1,
   d1 = {"..."},
   d2 = {"Lcom/bennyhuo/kotlinspecifics/reflect/SubClass;", "Lcom/bennyhuo/kotlinspecifics/reflect/SuperClass;", "()V", "Companion", "production sources for module app"}
)
public final class SubClass extends SuperClass {
    ...
}

上面给出的是 SubClass 编译后的字节码反编译得到的 Java 代码,我们看到 Metadata 这个注解当中包含了很多信息,其中 d2 当中就包含了这个类所有的父类信息。

这时候想必各位同仁已然猜到了,其实 Kotlin 反射获取信息的过程就是一个注解读取的过程。

混淆有何罪过

既然知道了 Kotlin 反射的原理,那么我们来想想混淆,混淆对于类的处理,对于通过字面量反射操作类和对象来说是致命的,因为字面量不会作为混淆的对象。同样的,前面的注解的值也不会。也真是这个原因,混淆后 SuperClass 被混淆为了 aSubClass 的注解中存的仍然是 SuperClass

没错,混淆之后出现找不到类的问题是合乎情理的。只要是通过字面量反射操作类和对象,无论是直接还是间接,都需要注意混淆的问题。

如果大家不信,大家也可以试一下属性引用或者函数引用,看看他们在被混淆之后有什么情况发生。

那么这个应该是混淆的锅咯?当然不是,Kotlin 反射毕竟有点儿曲线救国的意思,混淆也只能长叹一口气,“你们这。。让我防不胜防啊”。

有解决方案吗?

有啊,凡涉及到使用 Kotlin 反射的类及其父类(接口)、属性、函数等,均要小心这个问题,如果出现无法找到类或者属性、函数的情形,记得 Keep 它们。

最后再说一句

解析注解这种操作。。。额,难怪它慢。。


本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Kotlin 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概要
  • 问题的产生
  • Kotlin 反射的小伎俩
  • 混淆有何罪过
  • 有解决方案吗?
  • 最后再说一句
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档