From 5cca06664615df31c9b7a16024acffb525da5133 Mon Sep 17 00:00:00 2001 From: Vojin Jovanovic Date: Thu, 25 Sep 2025 19:20:51 +0200 Subject: [PATCH] Fix constructor accessor checks --- .../Target_java_lang_invoke_MethodHandle.java | 7 ++++++- .../target/Target_java_lang_reflect_Constructor.java | 12 ++++++++++-- .../target/Target_java_lang_reflect_Method.java | 5 +++++ ...get_jdk_internal_reflect_ConstructorAccessor.java | 2 +- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/methodhandles/Target_java_lang_invoke_MethodHandle.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/methodhandles/Target_java_lang_invoke_MethodHandle.java index 3dd851cf95a1..74faf7e1a96e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/methodhandles/Target_java_lang_invoke_MethodHandle.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/methodhandles/Target_java_lang_invoke_MethodHandle.java @@ -53,6 +53,7 @@ import com.oracle.svm.core.reflect.target.Target_java_lang_reflect_Constructor; import com.oracle.svm.core.reflect.target.Target_java_lang_reflect_Field; import com.oracle.svm.core.reflect.target.Target_java_lang_reflect_Method; +import com.oracle.svm.core.reflect.target.Target_jdk_internal_reflect_ConstructorAccessor; import com.oracle.svm.core.reflect.target.Target_jdk_internal_reflect_MethodAccessor; import com.oracle.svm.core.util.VMError; @@ -280,8 +281,12 @@ private static SubstrateConstructorAccessor asConstructor(Target_java_lang_invok return getConstructorAccessor(constructor); } + @SuppressWarnings("DataFlowIssue") private static SubstrateConstructorAccessor getConstructorAccessor(Constructor constructor) { - return SubstrateUtil.cast(SubstrateUtil.cast(constructor, Target_java_lang_reflect_Constructor.class).acquireConstructorAccessor(), SubstrateConstructorAccessor.class); + Target_java_lang_reflect_Constructor internalConstructor = SubstrateUtil.cast(constructor, Target_java_lang_reflect_Constructor.class); + Target_jdk_internal_reflect_ConstructorAccessor constructorAccessor = internalConstructor.constructorAccessor; + var result = constructorAccessor == null ? internalConstructor.acquireConstructorAccessor() : constructorAccessor; + return SubstrateUtil.cast(result, SubstrateConstructorAccessor.class); } private static void checkMember(T member, boolean isStatic) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Constructor.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Constructor.java index 9984c682ec29..60f723cc0b2f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Constructor.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Constructor.java @@ -42,6 +42,7 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.annotate.TargetElement; +import com.oracle.svm.core.configure.RuntimeConditionSet; import com.oracle.svm.core.metadata.MetadataTracer; import com.oracle.svm.core.reflect.MissingReflectionRegistrationUtils; @@ -59,9 +60,13 @@ public final class Target_java_lang_reflect_Constructor { @Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = ParameterAnnotationsComputer.class)// byte[] parameterAnnotations; + /** + * Value of the accessor when `this` is in the image heap. `null` for run-time constructed + * constructors. + */ @Alias // @RecomputeFieldValue(kind = Kind.Custom, declClass = ExecutableAccessorComputer.class) // - Target_jdk_internal_reflect_ConstructorAccessor constructorAccessor; + public Target_jdk_internal_reflect_ConstructorAccessor constructorAccessor; /** * We need this indirection to use {@link #acquireConstructorAccessor()} for checking if @@ -85,7 +90,10 @@ public Target_jdk_internal_reflect_ConstructorAccessor acquireConstructorAccesso if (MetadataTracer.enabled()) { ConstructorUtil.traceConstructorAccess(SubstrateUtil.cast(this, Executable.class)); } - if (constructorAccessorFromMetadata == null) { + + RuntimeConditionSet conditions = SubstrateUtil.cast(this, Target_java_lang_reflect_AccessibleObject.class).conditions; + assert constructorAccessor == null : "acquireConstructorAccessor() method must not be called if instance is in image heap."; + if (constructorAccessorFromMetadata == null || !conditions.satisfied()) { throw MissingReflectionRegistrationUtils.reportInvokedExecutable(SubstrateUtil.cast(this, Executable.class)); } return constructorAccessorFromMetadata; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Method.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Method.java index a4e51e883e0a..98e7364f5ead 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Method.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_java_lang_reflect_Method.java @@ -75,6 +75,10 @@ public final class Target_java_lang_reflect_Method { @Alias @RecomputeFieldValue(kind = Kind.Custom, declClass = AnnotationDefaultComputer.class)// byte[] annotationDefault; + /** + * Value of the accessor when `this` is in the image heap. `null` for run-time constructed + * methods. + */ @Alias // @RecomputeFieldValue(kind = Kind.Custom, declClass = ExecutableAccessorComputer.class) // public Target_jdk_internal_reflect_MethodAccessor methodAccessor; @@ -140,6 +144,7 @@ public Target_jdk_internal_reflect_MethodAccessor acquireMethodAccessor() { if (MetadataTracer.enabled()) { MethodUtil.traceMethodAccess(SubstrateUtil.cast(this, Executable.class)); } + assert methodAccessor == null : "acquireMethodAccessor() method must not be called if `this` is in image heap."; if (methodAccessorFromMetadata == null || !conditions.satisfied()) { throw MissingReflectionRegistrationUtils.reportInvokedExecutable(SubstrateUtil.cast(this, Executable.class)); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_ConstructorAccessor.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_ConstructorAccessor.java index c85eb65da81f..0a5f79c2f240 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_ConstructorAccessor.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_ConstructorAccessor.java @@ -27,5 +27,5 @@ import com.oracle.svm.core.annotate.TargetClass; @TargetClass(className = "jdk.internal.reflect.ConstructorAccessor") -final class Target_jdk_internal_reflect_ConstructorAccessor { +public final class Target_jdk_internal_reflect_ConstructorAccessor { }