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 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 jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||||
val member: Member? = when (jvmSignature) {
|
val member: Member? = when (jvmSignature) {
|
||||||
is KotlinConstructor -> {
|
is KotlinConstructor -> {
|
||||||
@@ -90,7 +90,7 @@ internal class KFunctionImpl private constructor(
|
|||||||
}.createInlineClassAwareCallerIfNeeded(descriptor)
|
}.createInlineClassAwareCallerIfNeeded(descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val defaultCaller: Caller<*>? by ReflectProperties.lazySoft defaultCaller@{
|
override val defaultCaller: Caller<*>? by ReflectProperties.lazy defaultCaller@{
|
||||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||||
val member: Member? = when (jvmSignature) {
|
val member: Member? = when (jvmSignature) {
|
||||||
is KotlinFunction -> {
|
is KotlinFunction -> {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
|||||||
|
|
||||||
override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER
|
override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER
|
||||||
|
|
||||||
private val _javaField = ReflectProperties.lazySoft {
|
private val _javaField = ReflectProperties.lazy {
|
||||||
val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)
|
val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)
|
||||||
when (jvmSignature) {
|
when (jvmSignature) {
|
||||||
is KotlinProperty -> {
|
is KotlinProperty -> {
|
||||||
@@ -152,7 +152,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
|||||||
property.descriptor.getter ?: DescriptorFactory.createDefaultGetter(property.descriptor, Annotations.EMPTY)
|
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)
|
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)
|
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)
|
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.
|
* 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?>(
|
internal class InlineClassAwareCaller<out M : Member?>(
|
||||||
private val descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
private val caller: Caller<M>,
|
private val caller: Caller<M>,
|
||||||
private val isDefault: Boolean
|
private val isDefault: Boolean
|
||||||
) : Caller<M> {
|
) : Caller<M> {
|
||||||
@@ -43,14 +43,14 @@ internal class InlineClassAwareCaller<out M : Member?>(
|
|||||||
operator fun component3(): Method? = box
|
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)
|
val box = descriptor.returnType!!.toInlineClass()?.getBoxMethod(descriptor)
|
||||||
|
|
||||||
if (descriptor.isGetterOfUnderlyingPropertyOfInlineClass()) {
|
if (descriptor.isGetterOfUnderlyingPropertyOfInlineClass()) {
|
||||||
// Getter of the underlying val of an inline class is always called on a boxed receiver,
|
// Getter of the underlying val of an inline class is always called on a boxed receiver,
|
||||||
// no argument boxing/unboxing is required.
|
// no argument boxing/unboxing is required.
|
||||||
// However, its result might require boxing if it is an inline class type.
|
// 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 {
|
val shift = when {
|
||||||
|
|||||||
Reference in New Issue
Block a user