Skip to content

Commit

Permalink
Removed strict rule -dontwarn java.lang.ClassValue (#2123)
Browse files Browse the repository at this point in the history
The `-dontwarn java.lang.ClassValue` rule embedded in serialization may have a side effect for the target application if it uses `java.lang.ClassValue` too.
Instead of this rule, it is enough to disable warnings for ClassValue inheritors in the serialization itself.

Resolves #2119
  • Loading branch information
shanshin authored Dec 19, 2022
1 parent 67e9259 commit 74f122b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 26 deletions.
48 changes: 24 additions & 24 deletions core/jvmMain/src/kotlinx/serialization/internal/Caching.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,41 +40,41 @@ internal actual fun <T> createParametrizedCache(factory: (KClass<Any>, List<KTyp
return if (useClassValue) ClassValueParametrizedCache(factory) else ConcurrentHashMapParametrizedCache(factory)
}

@SuppressAnimalSniffer
private class ClassValueCache<T>(private val compute: (KClass<*>) -> KSerializer<T>?) : SerializerCache<T> {
private val classValue = initClassValue()

private fun initClassValue() = object : ClassValue<CacheEntry<T>>() {
/*
* Since during the computing of the value for the `ClassValue` entry, we do not know whether a nullable
* serializer is needed, so we may need to differentiate nullable/non-null caches by a level higher
*/
override fun computeValue(type: Class<*>): CacheEntry<T> {
return CacheEntry(compute(type.kotlin))
}
}
private class ClassValueCache<T>(compute: (KClass<*>) -> KSerializer<T>?) : SerializerCache<T> {
private val classValue = ClassValueWrapper(compute)

override fun get(key: KClass<Any>): KSerializer<T>? = classValue[key.java].serializer
}

@SuppressAnimalSniffer
private class ClassValueParametrizedCache<T>(private val compute: (KClass<Any>, List<KType>) -> KSerializer<T>?) : ParametrizedSerializerCache<T> {
private val classValue = initClassValue()

private fun initClassValue() = object : ClassValue<ParametrizedCacheEntry<T>>() {
/*
* Since during the computing of the value for the `ClassValue` entry, we do not know whether a nullable
* serializer is needed, so we may need to differentiate nullable/non-null caches by a level higher
*/
override fun computeValue(type: Class<*>): ParametrizedCacheEntry<T> {
return ParametrizedCacheEntry()
}
private class ClassValueWrapper<T>(private val compute: (KClass<*>) -> KSerializer<T>?): ClassValue<CacheEntry<T>>() {
/*
* Since during the computing of the value for the `ClassValue` entry, we do not know whether a nullable
* serializer is needed, so we may need to differentiate nullable/non-null caches by a level higher
*/
override fun computeValue(type: Class<*>): CacheEntry<T> {
return CacheEntry(compute(type.kotlin))
}
}

private class ClassValueParametrizedCache<T>(private val compute: (KClass<Any>, List<KType>) -> KSerializer<T>?) : ParametrizedSerializerCache<T> {
private val classValue = ParametrizedClassValueWrapper<T>()

override fun get(key: KClass<Any>, types: List<KType>): Result<KSerializer<T>?> =
classValue[key.java].computeIfAbsent(types) { compute(key, types) }
}

@SuppressAnimalSniffer
private class ParametrizedClassValueWrapper<T> : ClassValue<ParametrizedCacheEntry<T>>() {
/*
* Since during the computing of the value for the `ClassValue` entry, we do not know whether a nullable
* serializer is needed, so we may need to differentiate nullable/non-null caches by a level higher
*/
override fun computeValue(type: Class<*>): ParametrizedCacheEntry<T> {
return ParametrizedCacheEntry()
}
}

/**
* We no longer support Java 6, so the only place we use this cache is Android, where there
* are no classloader leaks issue, thus we can safely use strong references and do not bother
Expand Down
7 changes: 5 additions & 2 deletions rules/common.pro
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@
# See also https://github.com/Kotlin/kotlinx.serialization/issues/1900
-dontnote kotlinx.serialization.**

# Serialization core uses `Class.forName("java.lang.ClassValue")` for caching in JVM-only, so it is an expected situation that this class is not in Android
-dontwarn java.lang.ClassValue
# Serialization core uses `java.lang.ClassValue` for caching inside these specified classes.
# If there is no `java.lang.ClassValue` (for example, in Android), then R8/ProGuard will print a warning.
# However, since in this case they will not be used, we can disable these warnings
-dontwarn kotlinx.serialization.internal.ClassValueWrapper
-dontwarn kotlinx.serialization.internal.ParametrizedClassValueWrapper

0 comments on commit 74f122b

Please sign in to comment.