Do not store JVM reflection objects by soft reference
Otherwise they might be garbage-collected before being made accessible with `isAccessible = true` and the reflective call. Also, compute BoxUnboxData in InlineClassAwareCaller right away, to prevent storing a hard reference on the descriptor (all descriptors and related data are stored by soft references in kotlin-reflect). #KT-27585 Fixed
This commit is contained in:
@@ -58,7 +58,7 @@ internal class KFunctionImpl private constructor(
|
||||
|
||||
override val name: String get() = descriptor.name.asString()
|
||||
|
||||
override val caller: Caller<*> by ReflectProperties.lazySoft caller@{
|
||||
override val caller: Caller<*> by ReflectProperties.lazy caller@{
|
||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||
val member: Member? = when (jvmSignature) {
|
||||
is KotlinConstructor -> {
|
||||
@@ -90,7 +90,7 @@ internal class KFunctionImpl private constructor(
|
||||
}.createInlineClassAwareCallerIfNeeded(descriptor)
|
||||
}
|
||||
|
||||
override val defaultCaller: Caller<*>? by ReflectProperties.lazySoft defaultCaller@{
|
||||
override val defaultCaller: Caller<*>? by ReflectProperties.lazy defaultCaller@{
|
||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||
val member: Member? = when (jvmSignature) {
|
||||
is KotlinFunction -> {
|
||||
|
||||
@@ -48,7 +48,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
||||
|
||||
override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER
|
||||
|
||||
private val _javaField = ReflectProperties.lazySoft {
|
||||
private val _javaField = ReflectProperties.lazy {
|
||||
val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)
|
||||
when (jvmSignature) {
|
||||
is KotlinProperty -> {
|
||||
@@ -152,7 +152,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
||||
property.descriptor.getter ?: DescriptorFactory.createDefaultGetter(property.descriptor, Annotations.EMPTY)
|
||||
}
|
||||
|
||||
override val caller: Caller<*> by ReflectProperties.lazySoft {
|
||||
override val caller: Caller<*> by ReflectProperties.lazy {
|
||||
computeCallerForAccessor(isGetter = true)
|
||||
}
|
||||
}
|
||||
@@ -165,7 +165,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
||||
property.descriptor.setter ?: DescriptorFactory.createDefaultSetter(property.descriptor, Annotations.EMPTY, Annotations.EMPTY)
|
||||
}
|
||||
|
||||
override val caller: Caller<*> by ReflectProperties.lazySoft {
|
||||
override val caller: Caller<*> by ReflectProperties.lazy {
|
||||
computeCallerForAccessor(isGetter = false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import kotlin.reflect.jvm.internal.toJavaClass
|
||||
* Each argument of an inline class type is unboxed, and the return value (if it's of an inline class type) is boxed.
|
||||
*/
|
||||
internal class InlineClassAwareCaller<out M : Member?>(
|
||||
private val descriptor: CallableMemberDescriptor,
|
||||
descriptor: CallableMemberDescriptor,
|
||||
private val caller: Caller<M>,
|
||||
private val isDefault: Boolean
|
||||
) : Caller<M> {
|
||||
@@ -43,14 +43,14 @@ internal class InlineClassAwareCaller<out M : Member?>(
|
||||
operator fun component3(): Method? = box
|
||||
}
|
||||
|
||||
private val data: BoxUnboxData by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
private val data: BoxUnboxData = run {
|
||||
val box = descriptor.returnType!!.toInlineClass()?.getBoxMethod(descriptor)
|
||||
|
||||
if (descriptor.isGetterOfUnderlyingPropertyOfInlineClass()) {
|
||||
// Getter of the underlying val of an inline class is always called on a boxed receiver,
|
||||
// no argument boxing/unboxing is required.
|
||||
// However, its result might require boxing if it is an inline class type.
|
||||
return@lazy BoxUnboxData(IntRange.EMPTY, emptyArray(), box)
|
||||
return@run BoxUnboxData(IntRange.EMPTY, emptyArray(), box)
|
||||
}
|
||||
|
||||
val shift = when {
|
||||
@@ -196,4 +196,4 @@ internal fun Any?.coerceToExpectedReceiverType(descriptor: CallableMemberDescrip
|
||||
val unboxMethod = expectedReceiverType?.toInlineClass()?.getUnboxMethod(descriptor) ?: return this
|
||||
|
||||
return unboxMethod.invoke(this)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user