Skip to content

Commit

Permalink
Automatically register nested Kotlin classes for reflection
Browse files Browse the repository at this point in the history
Users have come to expect that @RegisterForReflection fixes
a lot of native image issues and use it a lot.
For Kotlin classes however, registering a class is often not
enough - the companion classes are need to be registered.
These companion classes are nested classes, so we automatically
set the property to true for Kotlin classes

Closes: quarkusio#28167
  • Loading branch information
geoand committed Nov 3, 2022
1 parent 422a492 commit 6274863
Showing 1 changed file with 16 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.jboss.jandex.Type.Kind;
import org.jboss.logging.Logger;

import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Capability;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
Expand All @@ -32,8 +34,10 @@ public class RegisterForReflectionBuildStep {

private static final Logger log = Logger.getLogger(RegisterForReflectionBuildStep.class);

private static final DotName KOTLIN_METADATA_ANNOTATION = DotName.createSimple("kotlin.Metadata");

@BuildStep
public void build(CombinedIndexBuildItem combinedIndexBuildItem,
public void build(CombinedIndexBuildItem combinedIndexBuildItem, Capabilities capabilities,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<ReflectiveHierarchyBuildItem> reflectiveClassHierarchy,
BuildProducer<LambdaCapturingTypeBuildItem> lambdaCapturingTypeProducer) {
Expand Down Expand Up @@ -63,6 +67,12 @@ public void build(CombinedIndexBuildItem combinedIndexBuildItem,
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (targetsValue == null && classNamesValue == null) {
ClassInfo classInfo = i.target().asClass();
if (capabilities.isPresent(Capability.KOTLIN) && ignoreNested) {
// for Kotlin classes, we need to register the nested classes as well because companion classes are very often necessary at runtime
if (isKotlinClass(classInfo)) {
ignoreNested = false;
}
}
registerClass(classLoader, classInfo.name().toString(), methods, fields, ignoreNested, serialization,
reflectiveClass, reflectiveClassHierarchy, processedReflectiveHierarchies, registerFullHierarchyVaue,
builder);
Expand All @@ -88,6 +98,10 @@ public void build(CombinedIndexBuildItem combinedIndexBuildItem,
}
}

private static boolean isKotlinClass(ClassInfo classInfo) {
return classInfo.hasDeclaredAnnotation(KOTLIN_METADATA_ANNOTATION);
}

/**
* BFS Recursive Method to register a class and it's inner classes for Reflection.
*
Expand Down Expand Up @@ -213,4 +227,4 @@ private static Type getMethodReturnType(IndexView indexView, DotName initialName
private static boolean getBooleanValue(AnnotationInstance i, String name) {
return i.value(name) == null || i.value(name).asBoolean();
}
}
}

0 comments on commit 6274863

Please sign in to comment.