Skip to content

Commit 6e4007d

Browse files
authored
Merge pull request #223 from ProjectMapK/opt-jc-cache
Optimization for Java Class retrieval.
2 parents e02c9b1 + b2cfcb9 commit 6e4007d

File tree

9 files changed

+47
-29
lines changed

9 files changed

+47
-29
lines changed

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ClosedRangeSupport.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ internal object ClosedRangeResolver : SimpleAbstractTypeResolver() {
5555
}
5656

5757
fun findClosedFloatingPointRangeRef(contentType: Class<*>): Class<*>? = when (contentType) {
58-
Double::class.javaPrimitiveType, Double::class.javaObjectType -> closedDoubleRangeRef
59-
Float::class.javaPrimitiveType, Float::class.javaObjectType -> closedFloatRangeRef
58+
Double::class.java, Double::class.javaObjectType -> closedDoubleRangeRef
59+
Float::class.java, Float::class.javaObjectType -> closedFloatRangeRef
6060
else -> null
6161
}
6262

@@ -67,7 +67,7 @@ internal object ClosedRangeResolver : SimpleAbstractTypeResolver() {
6767
override fun findTypeMapping(config: DeserializationConfig, type: JavaType): JavaType? {
6868
val rawClass = type.rawClass
6969

70-
return if (rawClass == ClosedRange::class.java || rawClass == ClosedFloatingPointRange::class.java) {
70+
return if (rawClass == ClosedRange::class.java || rawClass == CLOSED_FLOATING_POINT_RANGE_CLASS) {
7171
type.bindings.typeParameters.firstOrNull()
7272
?.let { typeParam ->
7373
findClosedFloatingPointRangeRef(typeParam.rawClass)?.let {

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/InternalCommons.kt

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.github.projectmapk.jackson.module.kogera
22

33
import com.fasterxml.jackson.annotation.JsonCreator
4+
import com.fasterxml.jackson.annotation.JsonProperty
5+
import io.github.projectmapk.jackson.module.kogera.annotation.JsonKUnbox
46
import kotlinx.metadata.KmClass
57
import kotlinx.metadata.KmClassifier
68
import kotlinx.metadata.KmType
@@ -14,25 +16,25 @@ import java.lang.reflect.Method
1416
internal typealias JavaDuration = java.time.Duration
1517
internal typealias KotlinDuration = kotlin.time.Duration
1618

17-
internal fun Class<*>.toKmClass(): KmClass? = getAnnotation(Metadata::class.java)?.let {
19+
internal fun Class<*>.toKmClass(): KmClass? = getAnnotation(METADATA_CLASS)?.let {
1820
(KotlinClassMetadata.readStrict(it) as KotlinClassMetadata.Class).kmClass
1921
}
2022

21-
internal fun Class<*>.isUnboxableValueClass() = this.isAnnotationPresent(JvmInline::class.java)
23+
internal fun Class<*>.isUnboxableValueClass() = this.isAnnotationPresent(JVM_INLINE_CLASS)
2224

2325
// JmClass must be value class.
2426
internal fun JmClass.wrapsNullValueClass() = inlineClassUnderlyingType!!.isNullable
2527

2628
private val primitiveClassToDesc = mapOf(
27-
Byte::class.javaPrimitiveType to 'B',
28-
Char::class.javaPrimitiveType to 'C',
29-
Double::class.javaPrimitiveType to 'D',
30-
Float::class.javaPrimitiveType to 'F',
31-
Int::class.javaPrimitiveType to 'I',
32-
Long::class.javaPrimitiveType to 'J',
33-
Short::class.javaPrimitiveType to 'S',
34-
Boolean::class.javaPrimitiveType to 'Z',
35-
Void::class.javaPrimitiveType to 'V'
29+
Byte::class.java to 'B',
30+
Char::class.java to 'C',
31+
Double::class.java to 'D',
32+
Float::class.java to 'F',
33+
Int::class.java to 'I',
34+
Long::class.java to 'J',
35+
Short::class.java to 'S',
36+
Boolean::class.java to 'Z',
37+
Void.TYPE to 'V'
3638
)
3739

3840
// -> this.name.replace(".", "/")
@@ -88,6 +90,19 @@ internal fun String.reconstructClass(): Class<*> {
8890
internal fun KmType.reconstructClassOrNull(): Class<*>? = (classifier as? KmClassifier.Class)
8991
?.let { kotlin.runCatching { it.name.reconstructClass() }.getOrNull() }
9092

91-
internal fun AnnotatedElement.hasCreatorAnnotation(): Boolean = getAnnotation(JsonCreator::class.java)
93+
internal fun AnnotatedElement.hasCreatorAnnotation(): Boolean = getAnnotation(JSON_CREATOR_CLASS)
9294
?.let { it.mode != JsonCreator.Mode.DISABLED }
9395
?: false
96+
97+
// Instantiating Java Class as a static property is expected to improve first-time execution performance.
98+
// However, maybe this improvement is limited to Java Classes that are not used to initialize static content.
99+
// Also, for classes that are read at the time of initialization of static content or module initialization,
100+
// optimization seems unnecessary because caching is effective.
101+
internal val METADATA_CLASS = Metadata::class.java
102+
internal val JVM_INLINE_CLASS = JvmInline::class.java
103+
internal val JSON_CREATOR_CLASS = JsonCreator::class.java
104+
internal val JSON_PROPERTY_CLASS = JsonProperty::class.java
105+
internal val JSON_K_UNBOX_CLASS = JsonKUnbox::class.java
106+
internal val KOTLIN_DURATION_CLASS = KotlinDuration::class.java
107+
internal val CLOSED_FLOATING_POINT_RANGE_CLASS = ClosedFloatingPointRange::class.java
108+
internal val ANY_CLASS = Any::class.java

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/KotlinClassIntrospector.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ internal object KotlinClassIntrospector : BasicClassIntrospector() {
5050
?: run {
5151
val coll = collectProperties(config, type, r, true)
5252

53-
if (type.rawClass.isAnnotationPresent(Metadata::class.java)) {
53+
if (type.rawClass.isAnnotationPresent(METADATA_CLASS)) {
5454
KotlinBeanDescription(coll)
5555
} else {
5656
BasicBeanDescription.forDeserialization(coll)
@@ -71,7 +71,7 @@ internal object KotlinClassIntrospector : BasicClassIntrospector() {
7171
?: run {
7272
val coll = collectProperties(config, type, r, false)
7373

74-
if (type.rawClass.isAnnotationPresent(Metadata::class.java)) {
74+
if (type.rawClass.isAnnotationPresent(METADATA_CLASS)) {
7575
KotlinBeanDescription(coll)
7676
} else {
7777
BasicBeanDescription.forDeserialization(coll)

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ReflectionCache.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ internal class ReflectionCache(initialCacheSize: Int, maxCacheSize: Int) : Seria
5454
val superJmClass = if (!clazz.isInterface) {
5555
clazz.superclass?.let {
5656
// Stop parsing when `Object` is reached
57-
if (it != Any::class.java) getJmClass(it) else null
57+
if (it != ANY_CLASS) getJmClass(it) else null
5858
}
5959
} else {
6060
null

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/annotationIntrospector/KotlinFallbackAnnotationIntrospector.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMethod
1212
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter
1313
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector
1414
import com.fasterxml.jackson.databind.util.Converter
15-
import io.github.projectmapk.jackson.module.kogera.KotlinDuration
15+
import io.github.projectmapk.jackson.module.kogera.JSON_K_UNBOX_CLASS
16+
import io.github.projectmapk.jackson.module.kogera.KOTLIN_DURATION_CLASS
1617
import io.github.projectmapk.jackson.module.kogera.ReflectionCache
17-
import io.github.projectmapk.jackson.module.kogera.annotation.JsonKUnbox
1818
import io.github.projectmapk.jackson.module.kogera.isUnboxableValueClass
1919
import io.github.projectmapk.jackson.module.kogera.reconstructClassOrNull
2020
import io.github.projectmapk.jackson.module.kogera.ser.KotlinDurationValueToJavaDurationConverter
@@ -74,15 +74,15 @@ internal class KotlinFallbackAnnotationIntrospector(
7474
override fun findSerializationConverter(a: Annotated): Converter<*, *>? = when (a) {
7575
// Find a converter to handle the case where the getter returns an unboxed value from the value class.
7676
is AnnotatedMethod -> cache.findBoxedReturnType(a.member)?.let {
77-
if (useJavaDurationConversion && it == KotlinDuration::class.java) {
78-
if (a.rawReturnType == KotlinDuration::class.java) {
77+
if (useJavaDurationConversion && it == KOTLIN_DURATION_CLASS) {
78+
if (a.rawReturnType == KOTLIN_DURATION_CLASS) {
7979
KotlinToJavaDurationConverter
8080
} else {
8181
KotlinDurationValueToJavaDurationConverter
8282
}
8383
} else {
8484
// If JsonUnbox is specified, the unboxed getter is used as is.
85-
if (a.hasAnnotation(JsonKUnbox::class.java) || it.isAnnotationPresent(JsonKUnbox::class.java)) {
85+
if (a.hasAnnotation(JSON_K_UNBOX_CLASS) || it.isAnnotationPresent(JSON_K_UNBOX_CLASS)) {
8686
null
8787
} else {
8888
cache.getValueClassBoxConverter(a.rawReturnType, it)
@@ -95,7 +95,7 @@ internal class KotlinFallbackAnnotationIntrospector(
9595

9696
private fun lookupKotlinTypeConverter(a: AnnotatedClass) = when {
9797
Sequence::class.java.isAssignableFrom(a.rawType) -> SequenceToIteratorConverter(a.type)
98-
KotlinDuration::class.java == a.rawType -> KotlinToJavaDurationConverter.takeIf { useJavaDurationConversion }
98+
KOTLIN_DURATION_CLASS == a.rawType -> KotlinToJavaDurationConverter.takeIf { useJavaDurationConversion }
9999
else -> null
100100
}
101101

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/annotationIntrospector/KotlinPrimaryAnnotationIntrospector.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedMethod
1212
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter
1313
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector
1414
import com.fasterxml.jackson.databind.jsontype.NamedType
15+
import io.github.projectmapk.jackson.module.kogera.JSON_PROPERTY_CLASS
1516
import io.github.projectmapk.jackson.module.kogera.JmClass
1617
import io.github.projectmapk.jackson.module.kogera.ReflectionCache
1718
import io.github.projectmapk.jackson.module.kogera.hasCreatorAnnotation
@@ -42,7 +43,7 @@ internal class KotlinPrimaryAnnotationIntrospector(
4243
// If JsonProperty.required is true, the behavior is clearly specified and the result is paramount.
4344
// Otherwise, the required is determined from the configuration and the definition on Kotlin.
4445
override fun hasRequiredMarker(m: AnnotatedMember): Boolean? {
45-
val byAnnotation = _findAnnotation(m, JsonProperty::class.java)
46+
val byAnnotation = _findAnnotation(m, JSON_PROPERTY_CLASS)
4647
?.let { if (it.required) return true else false }
4748

4849
return cache.getJmClass(m.member.declaringClass)?.let {

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/valueInstantiator/creator/ConstructorValueCreator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ internal class ConstructorValueCreator<T : Any>(
4545
val parameterSize = it.size
4646
val temp = it.copyOf(parameterSize + maskSize + 1)
4747
for (i in 0 until maskSize) {
48-
temp[it.size + i] = Int::class.javaPrimitiveType
48+
temp[it.size + i] = Int::class.java
4949
}
5050
temp[parameterSize + maskSize] = defaultConstructorMarker
5151

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/deser/valueInstantiator/creator/MethodValueCreator.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.github.projectmapk.jackson.module.kogera.deser.valueInstantiator.creator
22

3+
import io.github.projectmapk.jackson.module.kogera.ANY_CLASS
34
import io.github.projectmapk.jackson.module.kogera.JmClass
45
import io.github.projectmapk.jackson.module.kogera.ReflectionCache
56
import io.github.projectmapk.jackson.module.kogera.call
@@ -50,9 +51,9 @@ internal class MethodValueCreator<T>(
5051
temp[0] = companionObjectClass // companion object
5152
parameterTypes.copyInto(temp, 1) // parameter types
5253
for (i in (valueParameterSize + 1)..(valueParameterSize + maskSize)) { // masks
53-
temp[i] = Int::class.javaPrimitiveType
54+
temp[i] = Int::class.java
5455
}
55-
temp[valueParameterSize + maskSize + 1] = Object::class.java // maker
56+
temp[valueParameterSize + maskSize + 1] = ANY_CLASS // maker
5657
temp
5758
} as Array<Class<*>>
5859

src/main/kotlin/io/github/projectmapk/jackson/module/kogera/ser/Converters.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.JavaType
44
import com.fasterxml.jackson.databind.type.TypeFactory
55
import com.fasterxml.jackson.databind.util.StdConverter
66
import io.github.projectmapk.jackson.module.kogera.JavaDuration
7+
import io.github.projectmapk.jackson.module.kogera.KOTLIN_DURATION_CLASS
78
import io.github.projectmapk.jackson.module.kogera.KotlinDuration
89
import io.github.projectmapk.jackson.module.kogera.ValueClassBoxConverter
910
import kotlin.time.toJavaDuration
@@ -20,7 +21,7 @@ internal class SequenceToIteratorConverter(private val input: JavaType) : StdCon
2021
}
2122

2223
internal object KotlinDurationValueToJavaDurationConverter : StdConverter<Long, JavaDuration>() {
23-
private val boxConverter by lazy { ValueClassBoxConverter(Long::class.java, KotlinDuration::class.java) }
24+
private val boxConverter by lazy { ValueClassBoxConverter(Long::class.java, KOTLIN_DURATION_CLASS) }
2425

2526
override fun convert(value: Long): JavaDuration = KotlinToJavaDurationConverter.convert(boxConverter.convert(value))
2627
}

0 commit comments

Comments
 (0)