kotlinKotlinKotlin 知识

【kotlin】::class 引发的效率问题

2021-12-07  本文已影响0人  littlefogcat

今日遇到一个kotlin问题,synchronized(MyClass:class)效率比synchronized(MyClass:class.java)低很多,想了解原因,故研究一下。

一、对应Java代码

以下代码:

class MyClass {}

fun main() {
    val var1 = MyClass::class
    val var2 = MyClass::class.java
    println("$var1, $var2")
}

通过编译器反编译字节码,查看其对应的Java代码:

   public static final void main() {
      KClass var1 = Reflection.getOrCreateKotlinClass(MyClass.class);
      Class var2 = MyClass.class;
      String var3 = var1 + ", " + var2;
      System.out.println(var3);
   }

可以发现:

  1. MyClass::class对应的Java代码为Reflection.getOrCreateKotlinClass(MyClass.class)
  2. MyClass::class.java对应的Java代码为MyClass.class

二、源码分析

Reflection.getOrCreateKotlinClass代码如下:

    public static KClass getOrCreateKotlinClass(Class javaClass) {
        return factory.getOrCreateKotlinClass(javaClass);
    }

可以发现,这个factory其实是一个ReflectionFactory类型的对象,查看对应方法:

    public KClass getOrCreateKotlinClass(Class javaClass) {
        return new ClassReference(javaClass);
    }

也就是说,每次调用MyClass::class都会新创建一个ClassReference对象?

不是的。其实factory的真实类型是ReflectionFactoryImpl,其getOrCreateKotlinClass方法如下:

    public KClass getOrCreateKotlinClass(Class javaClass) {
        return KClassCacheKt.getOrCreateKotlinClass(javaClass);
    }

KClassCacheKt类包含了一个缓存的Map,当调用getOrCreateKotlinClass方法时,会从缓存中读取对应的KClass类型;如果缓存中没有的话,就创建一个对应的KClass对象并保存在Map中。

三、总结

在kotlin中第一次调用MyClass::class的时候,会创建一个KClassImpl对象并保存在缓存中;之后再次调用就直接从缓存中返回之。而调用MyClass::class.java时,则直接通过类加载器返回对应的Java类对象。

而开头遇到的效率问题,其实是MyClass::class第一次调用时创建KClass对象的额外开销。当然,在大多数情况下,并不会造成多大影响;在高性能需求的场景,可以提前调用MyClass::class创建KClass缓存。

上一篇下一篇

猜你喜欢

热点阅读