diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java index 346e976b6e50..32d56f788877 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/LayeredDispatchTableFeature.java @@ -65,6 +65,7 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.FeatureImpl.BeforeCompilationAccessImpl; +import com.oracle.svm.hosted.code.FactoryMethod; import com.oracle.svm.hosted.image.NativeImage; import com.oracle.svm.hosted.image.NativeImageCodeCache; import com.oracle.svm.hosted.meta.HostedMetaAccess; @@ -264,11 +265,20 @@ void installBuilderModules(Set newCoreTypes) { public void recordVirtualCallTarget(HostedMethod caller, HostedMethod callee) { Module callerModule = caller.getDeclaringClass().getJavaClass().getModule(); Module calleeModule = callee.getDeclaringClass().getJavaClass().getModule(); - if (!(builderModules.contains(callerModule) || builderModules.contains(calleeModule))) { + if (!(builderModules.contains(callerModule) && !isFactoryMethod(caller)) && !builderModules.contains(calleeModule)) { virtualCallTargets.add(callee); } } + /** + * {@link FactoryMethod FactoryMethods} outline the allocation and call to the original + * constructor. Hence, whether the call is included or not should be based exclusively on the + * callee. + */ + private static boolean isFactoryMethod(HostedMethod caller) { + return caller.getWrapped().getWrapped() instanceof FactoryMethod; + } + public void registerDeclaredDispatchInfo(HostedType type, List declaredMethods) { var dispatchTable = new HostedDispatchTable(); dispatchTable.type = type;