publicfinalclassTestKt { public static final void main() { KClass clz = Reflection . getOrCreateKotlinClass (Test.class); System.out.println(clz); } }
1 2 3 4 5 6 7 8
/** * This class serves as a facade to the actual reflection implementation. JVM back-end generates calls to static methods of this class * on any reflection-using construct. */ @SuppressWarnings({"unused", "rawtypes"}) publicclassReflection { //...... }
// TODO: collect nulls periodically // 核心 !!! // 这个map的key是Class.getName(),而value是WeakReference<KClassImpl<*>> or an Array<WeakReference<KClassImpl<*>>> // 之所以使用array是因为一个jclass可能被不同的classloader加载从而使得clz具有不同的实例.(你可以看见从map里面获取的kclass对比依据一是name,二就是jclass实现) // 除此之外这个map故意没有做线程同步,因为数据是否发生竞争或者丢失其实是不重要的. // 这里唯一需要关注就是访问的性能,因此没有做同步 // Key of the map is Class.getName(), each value is either a WeakReference<KClassImpl<*>> or an Array<WeakReference<KClassImpl<*>>>. // Arrays are needed because the same class can be loaded by different class loaders, which results in different Class instances. // This variable is not volatile intentionally: we don't care if there's a data race on it and some KClass instances will be lost. // We do care however about general performance on read access to it, thus no synchronization is done here whatsoever privatevar K_CLASS_CACHE = HashPMap.empty<String, Any>()
// 强调可能会被频繁调用,所以这里的性能比较重要 // This function is invoked on each reflection access to Java classes, properties, etc. Performance is critical here. internalfun<T : Any>getOrCreateKotlinClass(jClass: Class<T>): KClassImpl<T> { val name = jClass.name //从自定义的map里面去获取 val cached = K_CLASS_CACHE[name] //如果获取到值 if (cached is WeakReference<*>) { @Suppress("UNCHECKED_CAST") val kClass = cached.get() as KClassImpl<T>? if (kClass?.jClass == jClass) { //直接返回 return kClass } } elseif (cached != null) { // If the cached value is not a weak reference, it's an array of weak references // 如果不是weakReference那么就会是一个弱引用list @Suppress("UNCHECKED_CAST") (cached as Array<WeakReference<KClassImpl<T>>>) //遍历弱引用表,如果有就直接return for (ref in cached) { val kClass = ref.get() if (kClass?.jClass == jClass) { //直接返回 return kClass } }
// This is the most unlikely case: we found a cached array of references of length at least 2 (can't be 1 because // the single element would be cached instead), and none of those classes is the one we're looking for // 此处声明cache里面的class数目不太可能是1个,如果是一个会走上面的if分支.而且需要满足list内无满足条件的kclass才会执行到此处.
// 如果没有寻找到kclass就就new一个实现类放入list并存入map里面 val size = cached.size val newArray = arrayOfNulls<WeakReference<KClassImpl<*>>>(size + 1) // Don't use Arrays.copyOf because it works reflectively // 不要使用Arrays.copyOf因为他使用了反射 // 感兴趣的自己去看,Arrays.copyOf会通过反射创建数组,并调用Systm.arraycopy来实现数组的拷贝 // why?为什么这点性能都需要追求,因为在函数定义处dev给了我们解释: // 这个方法每当反射或者说::都会被调用,所以需要追求性能. System.arraycopy(cached, 0, newArray, 0, size) val newKClass = KClassImpl(jClass) newArray[size] = WeakReference(newKClass) K_CLASS_CACHE = K_CLASS_CACHE.plus(name, newArray) return newKClass }
@SuppressWarnings("unchecked") protected T unescape(Object value) { return value == NULL_VALUE ? null : (T) value; } }
接着看descriptor
1 2 3 4 5 6 7 8 9 10
val descriptor: ClassDescriptor by ReflectProperties.lazySoft { val classId = classId val moduleData = data().moduleData
val descriptor = if (classId.isLocal) moduleData.deserialization.deserializeClass(classId) else moduleData.module.findClassAcrossModuleDependencies(classId)
classRuntimeModuleDataprivateconstructor( val deserialization: DeserializationComponents, val packagePartScopeCache: PackagePartScopeCache ) { val module: ModuleDescriptor get() = deserialization.moduleDescriptor
companionobject { //创建并返回实例 funcreate(classLoader: ClassLoader): RuntimeModuleData { //这个类比较重要,他会去解析class的annotation中的metadata //这一解析就能得到一些raw data(干巴巴的数据),再进行一次解析就能转化为可使用的bean val kotlinClassFinder = ReflectKotlinClassFinder(classLoader) val moduleData = createModuleData( kotlinClassFinder = kotlinClassFinder, // .kotlin_builtins files should be found by the same class loader that loaded stdlib classes jvmBuiltInsKotlinClassFinder = ReflectKotlinClassFinder(Unit::class.java.classLoader), javaClassFinder = ReflectJavaClassFinder(classLoader), moduleName = "runtime module for $classLoader", errorReporter = RuntimeErrorReporter, javaSourceElementFactory = RuntimeSourceElementFactory ) return RuntimeModuleData( moduleData.deserializationComponentsForJava.components, PackagePartScopeCache(moduleData.deserializedDescriptorResolver, kotlinClassFinder) ) } } }
上述代码执行完毕以后就会一层层出栈,最后执行回到这里
1 2 3 4 5 6 7 8 9 10 11 12
val descriptor: ClassDescriptor by ReflectProperties.lazySoft { //finished val classId = classId val moduleData = data().moduleData //获取解析器,依据不同情况获取不同的解析器 val descriptor = if (classId.isLocal) moduleData.deserialization.deserializeClass(classId) //demo会走这一条 else moduleData.module.findClassAcrossModuleDependencies(classId)
@Override public String toString() { KCallablereflected= compute(); if (reflected != this) { return reflected.toString(); }
// TODO: consider adding the class name to toString() for constructors return"<init>".equals(getName()) ? "constructor" + Reflection.REFLECTION_NOT_AVAILABLE : "function " + getName() + Reflection.REFLECTION_NOT_AVAILABLE; } }
/** * A superclass for all classes generated by Kotlin compiler for callable references. * All methods from KCallable should be implemented here and should delegate to the actual implementation, loaded dynamically and stored in the reflected field. */ //简而言之就是具体实现function reflection的类 @SuppressWarnings({"unchecked", "NullableProblems", "rawtypes"}) publicabstractclassCallableReferenceimplementsKCallable, Serializable { // This field is not volatile intentionally: // 1) It's fine if the value is computed multiple times in different threads; // 2) An uninitialized value cannot be observed in this field from other thread because only already initialized or safely initialized // objects are written to it. The latter is guaranteed because both KFunctionImpl and KPropertyImpl have at least one final field. privatetransient KCallable reflected;
// The following methods provide the information identifying this callable, which is used by the reflection implementation and // by equals/hashCode/toString. For callable references compiled prior to 1.4, these methods were overridden in each subclass // (each anonymous class generated for a callable reference).
/** * @return the class or package where the callable should be located, usually specified on the LHS of the '::' operator */ public KDeclarationContainer getOwner() { return owner == null ? null : isTopLevel ? Reflection.getOrCreateKotlinPackage(owner) : Reflection.getOrCreateKotlinClass(owner); }
/** * @return Kotlin name of the callable, the one which was declared in the source code (@JvmName doesn't change it) */ @Override public String getName() { return name; }
/** * @return JVM signature of the callable, e.g. "println(Ljava/lang/Object;)V". If this is a property reference, * returns the JVM signature of its getter, e.g. "getFoo(Ljava/lang/String;)I". If the property has no getter in the bytecode * (e.g. private property in a class), it's still the signature of the imaginary default getter that would be generated otherwise. * * Note that technically the signature itself is not even used as a signature per se in reflection implementation, * but only as a unique and unambiguous way to map a function/property descriptor to a string. */ public String getSignature() { return signature; }
// The following methods are the delegating implementations of reflection functions. They are called when you're using reflection // on a callable reference. Without kotlin-reflect.jar in the classpath, getReflected() throws an exception.
@Override public List<KParameter> getParameters() { return getReflected().getParameters(); }
@Override public KType getReturnType() { return getReflected().getReturnType(); }
@Override public List<Annotation> getAnnotations() { return getReflected().getAnnotations(); }