Address classloader leak in a recently-introduced ClassValueCache

Root cause:

Cached in `ClassValue` values are prohibited to reference any `java.lang.Class` or `ClassValue` instances as they are considered as strong roots that prevent `Class` and `ClassValue` garbage collection,
creating effectively unloadable cycle.
This problem is also known as JDK-8136353.

Actions taken:

* Extract anonymous `ClassValue` instance into a separate *static* class that does not capture anything implicitly
* Wrap potentially leaking direct `Class` references into WeakReference
* Wrap complex descriptor-wrapping structures into LazySoft to minimize the codebase impact and cover all at once

Actions not taken:

* Each individual class from core:descriptors.runtime that references `java.lang.Class` is not modified.
  These classes are referenced by already soft-wrapped Data and are not cached otherwise
* Cached values are not wrapped into WeakReference. Even the simplest experiment shows significant GC pressure
   (that previous implementation was also prone to)

^KT-56093 Fixed
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/CacheByClass.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/CacheByClass.kt
index f95e0cc..6343ce8 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/CacheByClass.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/CacheByClass.kt
@@ -35,16 +35,18 @@
     return if (useClassValue) ClassValueCache(compute) else ConcurrentHashMapCache(compute)
 }
 
-private class ClassValueCache<V>(private val compute: (Class<*>) -> V) : CacheByClass<V>() {
+private class ComputableClassValue<V>(private val compute: (Class<*>) -> V) : ClassValue<V>() {
+    override fun computeValue(type: Class<*>): V {
+        return compute(type)
+    }
+
+    fun createNewCopy() = ComputableClassValue(compute)
+}
+
+private class ClassValueCache<V>(compute: (Class<*>) -> V) : CacheByClass<V>() {
 
     @Volatile
-    private var classValue = initClassValue()
-
-    private fun initClassValue() = object : ClassValue<V>() {
-        override fun computeValue(type: Class<*>): V {
-            return compute(type)
-        }
-    }
+    private var classValue = ComputableClassValue(compute)
 
     override fun get(key: Class<*>): V = classValue[key]
 
@@ -53,7 +55,7 @@
          * ClassValue does not have a proper `clear()` method but is properly weak-referenced,
          * thus abandoning ClassValue instance will eventually clear all associated values.
          */
-        classValue = initClassValue()
+        classValue = classValue.createNewCopy()
     }
 }
 
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt
index a7af316..ab55f65 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt
@@ -36,13 +36,14 @@
 import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
 import org.jetbrains.kotlin.utils.compact
+import java.lang.ref.WeakReference
 import kotlin.jvm.internal.TypeIntrinsics
 import kotlin.reflect.*
 import kotlin.reflect.jvm.internal.KDeclarationContainerImpl.MemberBelonginess.DECLARED
 import kotlin.reflect.jvm.internal.KDeclarationContainerImpl.MemberBelonginess.INHERITED
 
 internal class KClassImpl<T : Any>(
-    override val jClass: Class<T>
+    jClass: Class<T>
 ) : KDeclarationContainerImpl(), KClass<T>, KClassifierImpl, KTypeParameterOwnerImpl {
     inner class Data : KDeclarationContainerImpl.Data() {
         val descriptor: ClassDescriptor by ReflectProperties.lazySoft {
@@ -177,7 +178,11 @@
                 by ReflectProperties.lazySoft { allNonStaticMembers + allStaticMembers }
     }
 
-    val data = ReflectProperties.lazy { Data() }
+    private val weaklyReferencedJClass = WeakReference(jClass)
+
+    override val jClass: Class<T> get() = weaklyReferencedJClass.get() ?: nullClassWeakReference()
+
+    val data = ReflectProperties.lazySoft { Data() }
 
     override val descriptor: ClassDescriptor get() = data().descriptor
 
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt
index c3afae8..db5dd42 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPackageImpl.kt
@@ -32,11 +32,12 @@
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.resolve.scopes.MemberScope
 import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
+import java.lang.ref.WeakReference
 import kotlin.reflect.KCallable
 import kotlin.reflect.jvm.internal.KDeclarationContainerImpl.MemberBelonginess.DECLARED
 
 internal class KPackageImpl(
-    override val jClass: Class<*>,
+    jClass: Class<*>,
 ) : KDeclarationContainerImpl() {
     private inner class Data : KDeclarationContainerImpl.Data() {
         private val kotlinClass: ReflectKotlinClass? by ReflectProperties.lazySoft {
@@ -51,7 +52,7 @@
             else MemberScope.Empty
         }
 
-        val multifileFacade: Class<*>? by ReflectProperties.lazy {
+        val multifileFacade: Class<*>? by ReflectProperties.lazySoft {
             val facadeName = kotlinClass?.classHeader?.multifileClassName
             // We need to check isNotEmpty because this is the value read from the annotation which cannot be null.
             // The default value for 'xs' is empty string, as declared in kotlin.Metadata
@@ -76,7 +77,11 @@
         }
     }
 
-    private val data = ReflectProperties.lazy { Data() }
+    private val weaklyReferencedJClass: WeakReference<Class<*>> = WeakReference(jClass)
+
+    override val jClass: Class<*> get() = weaklyReferencedJClass.get() ?: nullClassWeakReference()
+
+    private val data = ReflectProperties.lazySoft { Data() }
 
     override val methodOwner: Class<*> get() = data().multifileFacade ?: jClass
 
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt
index f654b0a..5c4fa92 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt
@@ -47,6 +47,7 @@
 import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext
 import org.jetbrains.kotlin.serialization.deserialization.DeserializedArrayValue
 import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
+import java.lang.ref.WeakReference
 import java.lang.reflect.Type
 import kotlin.jvm.internal.FunctionReference
 import kotlin.jvm.internal.PropertyReference
@@ -298,3 +299,6 @@
     override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit): KCallableImpl<*> =
         KFunctionImpl(container, descriptor)
 }
+
+internal fun nullClassWeakReference(): Nothing =
+    error("Unexpected 'null' in WeakReference<Class> that indicates bug in reflection caching in the presence of multiple classloaders")