From 30bb4087167e230baadc551cd6d9eabc0a34f3c4 Mon Sep 17 00:00:00 2001 From: "cengfeng.lzy" Date: Wed, 21 Oct 2020 10:14:58 +0800 Subject: [PATCH] Exclude substituted class from build time initialization The class substituted with @Substitute or @Delete annotation should not be initialized at build time because it will not appear in the run time. It makes no sense to put it in the native heap but causing initialization errors. --- .../TypeInitializerGraph.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java index 281ae9e6f407..93422a639ca4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/TypeInitializerGraph.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.hosted.classinitialization; +import java.lang.annotation.Annotation; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -36,10 +37,14 @@ import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.svm.core.annotate.Delete; +import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.phases.SubstrateClassInitializationPlugin; import com.oracle.svm.hosted.substitute.SubstitutionMethod; +import com.oracle.svm.hosted.substitute.SubstitutionType; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Keeps a type-hierarchy dependency graph for {@link AnalysisType}s from {@code universe}. Each @@ -106,9 +111,24 @@ void computeInitializerSafety() { * A type initializer is initially unsafe only if it was marked by the user as such. */ private Safety initialTypeInitializerSafety(AnalysisType t) { - return classInitializationSupport.specifiedInitKindFor(t.getJavaClass()) == InitKind.BUILD_TIME || classInitializationSupport.canBeProvenSafe(t.getJavaClass()) - ? Safety.SAFE - : Safety.UNSAFE; + ResolvedJavaType rt = t.getWrappedWithoutResolve(); + boolean isSubstituted = false; + if (rt instanceof SubstitutionType) { + SubstitutionType substitutionType = (SubstitutionType) rt; + for (Annotation annotation : substitutionType.getAnnotations()) { + if (annotation instanceof Substitute || annotation instanceof Delete) { + isSubstituted = true; + break; + } + } + } + if(isSubstituted){ + return Safety.UNSAFE; + }else { + return classInitializationSupport.specifiedInitKindFor(t.getJavaClass()) == InitKind.BUILD_TIME || classInitializationSupport.canBeProvenSafe(t.getJavaClass()) + ? Safety.SAFE + : Safety.UNSAFE; + } } boolean isUnsafe(AnalysisType type) {