Reflection: fix exceptions on concurrent access to some properties
Using `ReflectionProperties.lazy` is incorrect because it allows several threads to observe different resulting values if they're computing it simultaneously (unlike `lazy(PUBLICATION)`, which always returns the value that "won the race"). In the case of property delegates, for example, if we're invoking `isAccessible = true` and then `getDelegate()` concurrently, it might happen that when some thread invokes `getDelegate()`, it gets the underlying Field object which was written by another thread and which has not yet been made accessible, leading to IllegalPropertyDelegateAccessException. #KT-27585 Fixed
This commit is contained in:
committed by
Space Team
parent
e8f95a3376
commit
99b38ccb74
@@ -23,6 +23,7 @@ import java.lang.reflect.Constructor
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.jvm.internal.CallableReference
|
||||
import kotlin.jvm.internal.FunctionBase
|
||||
import kotlin.reflect.KFunction
|
||||
@@ -58,7 +59,7 @@ internal class KFunctionImpl private constructor(
|
||||
|
||||
override val name: String get() = descriptor.name.asString()
|
||||
|
||||
override val caller: Caller<*> by ReflectProperties.lazy caller@{
|
||||
override val caller: Caller<*> by lazy(PUBLICATION) caller@{
|
||||
val member: Member? = when (val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)) {
|
||||
is KotlinConstructor -> {
|
||||
if (isAnnotationConstructor)
|
||||
@@ -89,7 +90,7 @@ internal class KFunctionImpl private constructor(
|
||||
}.createInlineClassAwareCallerIfNeeded(descriptor)
|
||||
}
|
||||
|
||||
override val defaultCaller: Caller<*>? by ReflectProperties.lazy defaultCaller@{
|
||||
override val defaultCaller: Caller<*>? by lazy(PUBLICATION) defaultCaller@{
|
||||
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
|
||||
val member: Member? = when (jvmSignature) {
|
||||
is KotlinFunction -> {
|
||||
|
||||
@@ -28,9 +28,9 @@ internal open class KProperty0Impl<out V> : KProperty0<V>, KPropertyImpl<V> {
|
||||
container, name, signature, boundReceiver
|
||||
)
|
||||
|
||||
private val _getter = ReflectProperties.lazy { Getter(this) }
|
||||
private val _getter = lazy(PUBLICATION) { Getter(this) }
|
||||
|
||||
override val getter: Getter<V> get() = _getter()
|
||||
override val getter: Getter<V> get() = _getter.value
|
||||
|
||||
override fun get(): V = getter.call()
|
||||
|
||||
@@ -52,9 +52,9 @@ internal class KMutableProperty0Impl<V> : KProperty0Impl<V>, KMutableProperty0<V
|
||||
container, name, signature, boundReceiver
|
||||
)
|
||||
|
||||
private val _setter = ReflectProperties.lazy { Setter(this) }
|
||||
private val _setter = lazy(PUBLICATION) { Setter(this) }
|
||||
|
||||
override val setter: Setter<V> get() = _setter()
|
||||
override val setter: Setter<V> get() = _setter.value
|
||||
|
||||
override fun set(value: V) = setter.call(value)
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ internal open class KProperty1Impl<T, out V> : KProperty1<T, V>, KPropertyImpl<V
|
||||
|
||||
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||
|
||||
private val _getter = ReflectProperties.lazy { Getter(this) }
|
||||
private val _getter = lazy(PUBLICATION) { Getter(this) }
|
||||
|
||||
override val getter: Getter<T, V> get() = _getter()
|
||||
override val getter: Getter<T, V> get() = _getter.value
|
||||
|
||||
override fun get(receiver: T): V = getter.call(receiver)
|
||||
|
||||
@@ -52,9 +52,9 @@ internal class KMutableProperty1Impl<T, V> : KProperty1Impl<T, V>, KMutablePrope
|
||||
|
||||
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||
|
||||
private val _setter = ReflectProperties.lazy { Setter(this) }
|
||||
private val _setter = lazy(PUBLICATION) { Setter(this) }
|
||||
|
||||
override val setter: Setter<T, V> get() = _setter()
|
||||
override val setter: Setter<T, V> get() = _setter.value
|
||||
|
||||
override fun set(receiver: T, value: V) = setter.call(receiver, value)
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ internal open class KProperty2Impl<D, E, out V> : KProperty2<D, E, V>, KProperty
|
||||
|
||||
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||
|
||||
private val _getter = ReflectProperties.lazy { Getter(this) }
|
||||
private val _getter = lazy(PUBLICATION) { Getter(this) }
|
||||
|
||||
override val getter: Getter<D, E, V> get() = _getter()
|
||||
override val getter: Getter<D, E, V> get() = _getter.value
|
||||
|
||||
override fun get(receiver1: D, receiver2: E): V = getter.call(receiver1, receiver2)
|
||||
|
||||
@@ -51,9 +51,9 @@ internal class KMutableProperty2Impl<D, E, V> : KProperty2Impl<D, E, V>, KMutabl
|
||||
|
||||
constructor(container: KDeclarationContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
|
||||
|
||||
private val _setter = ReflectProperties.lazy { Setter(this) }
|
||||
private val _setter = lazy(PUBLICATION) { Setter(this) }
|
||||
|
||||
override val setter: Setter<D, E, V> get() = _setter()
|
||||
override val setter: Setter<D, E, V> get() = _setter.value
|
||||
|
||||
override fun set(receiver1: D, receiver2: E, value: V) = setter.call(receiver1, receiver2, value)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import java.lang.reflect.*
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.jvm.internal.CallableReference
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KMutableProperty
|
||||
@@ -48,7 +49,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
|
||||
|
||||
override val isBound: Boolean get() = rawBoundReceiver != CallableReference.NO_RECEIVER
|
||||
|
||||
private val _javaField: ReflectProperties.LazyVal<Field?> = ReflectProperties.lazy {
|
||||
private val _javaField = lazy(PUBLICATION) {
|
||||
when (val jvmSignature = RuntimeTypeMapper.mapPropertySignature(descriptor)) {
|
||||
is KotlinProperty -> {
|
||||
val descriptor = jvmSignature.descriptor
|
||||
@@ -75,7 +76,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
val javaField: Field? get() = _javaField()
|
||||
val javaField: Field? get() = _javaField.value
|
||||
|
||||
protected fun computeDelegateSource(): Member? {
|
||||
if (!descriptor.isDelegated) return null
|
||||
@@ -175,7 +176,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
|
||||
property.descriptor.getter ?: DescriptorFactory.createDefaultGetter(property.descriptor, Annotations.EMPTY)
|
||||
}
|
||||
|
||||
override val caller: Caller<*> by ReflectProperties.lazy {
|
||||
override val caller: Caller<*> by lazy(PUBLICATION) {
|
||||
computeCallerForAccessor(isGetter = true)
|
||||
}
|
||||
|
||||
@@ -196,7 +197,7 @@ internal abstract class KPropertyImpl<out V> private constructor(
|
||||
property.descriptor.setter ?: DescriptorFactory.createDefaultSetter(property.descriptor, Annotations.EMPTY, Annotations.EMPTY)
|
||||
}
|
||||
|
||||
override val caller: Caller<*> by ReflectProperties.lazy {
|
||||
override val caller: Caller<*> by lazy(PUBLICATION) {
|
||||
computeCallerForAccessor(isGetter = false)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user