2424 */
2525package com .oracle .svm .hosted ;
2626
27- import com .oracle .svm .core .feature .InternalFeature ;
27+ import java .util .concurrent .ConcurrentHashMap ;
28+
29+ import com .oracle .graal .pointsto .heap .ImageHeapConstant ;
2830import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
31+ import com .oracle .svm .core .feature .InternalFeature ;
32+ import com .oracle .svm .core .fieldvaluetransformer .FieldValueTransformerWithAvailability ;
33+ import com .oracle .svm .core .imagelayer .ImageLayerBuildingSupport ;
34+ import com .oracle .svm .core .util .VMError ;
35+ import com .oracle .svm .hosted .imagelayer .CrossLayerConstantRegistry ;
36+ import com .oracle .svm .hosted .jdk .HostedClassLoaderPackageManagement ;
37+ import com .oracle .svm .util .ReflectionUtil ;
38+
39+ import jdk .internal .loader .ClassLoaders ;
2940
3041@ AutomaticallyRegisteredFeature
3142public class ClassLoaderFeature implements InternalFeature {
3243
44+ private static final String APP_KEY_NAME = "ClassLoader#App" ;
45+ private static final String PLATFORM_KEY_NAME = "ClassLoader#Platform" ;
46+ private static final String BOOT_KEY_NAME = "ClassLoader#Boot" ;
47+
3348 private static final NativeImageSystemClassLoader nativeImageSystemClassLoader = NativeImageSystemClassLoader .singleton ();
3449
50+ private static final ClassLoader bootClassLoader ;
51+ private static final ClassLoader platformClassLoader ;
52+
53+ static {
54+ if (ImageLayerBuildingSupport .buildingImageLayer ()) {
55+ platformClassLoader = ClassLoaders .platformClassLoader ();
56+ bootClassLoader = BootLoaderSupport .getBootLoader ();
57+ } else {
58+ platformClassLoader = null ;
59+ bootClassLoader = null ;
60+ }
61+ }
62+
3563 public static ClassLoader getRuntimeClassLoader (ClassLoader original ) {
36- if (needsReplacement (original )) {
64+ if (replaceWithAppClassLoader (original )) {
3765 return nativeImageSystemClassLoader .defaultSystemClassLoader ;
3866 }
67+
3968 return original ;
4069 }
4170
42- private static boolean needsReplacement (ClassLoader loader ) {
71+ private static boolean replaceWithAppClassLoader (ClassLoader loader ) {
4372 if (loader == nativeImageSystemClassLoader ) {
4473 return true ;
4574 }
@@ -50,14 +79,79 @@ private static boolean needsReplacement(ClassLoader loader) {
5079 }
5180
5281 private Object runtimeClassLoaderObjectReplacer (Object replaceCandidate ) {
53- if (replaceCandidate instanceof ClassLoader ) {
54- return getRuntimeClassLoader (( ClassLoader ) replaceCandidate );
82+ if (replaceCandidate instanceof ClassLoader loader ) {
83+ return getRuntimeClassLoader (loader );
5584 }
5685 return replaceCandidate ;
5786 }
5887
88+ ImageHeapConstant replaceClassLoadersWithLayerConstant (CrossLayerConstantRegistry registry , Object object ) {
89+ if (object instanceof ClassLoader loader ) {
90+ if (replaceWithAppClassLoader (loader ) || loader == nativeImageSystemClassLoader .defaultSystemClassLoader ) {
91+ return registry .getConstant (APP_KEY_NAME );
92+ } else if (loader == platformClassLoader ) {
93+ return registry .getConstant (PLATFORM_KEY_NAME );
94+ } else if (loader == bootClassLoader ) {
95+ return registry .getConstant (BOOT_KEY_NAME );
96+ } else {
97+ throw VMError .shouldNotReachHere ("Currently unhandled class loader seen in extension layer: %s" , loader );
98+ }
99+ }
100+
101+ return null ;
102+ }
103+
59104 @ Override
60105 public void duringSetup (DuringSetupAccess access ) {
61- access .registerObjectReplacer (this ::runtimeClassLoaderObjectReplacer );
106+ var packageManager = HostedClassLoaderPackageManagement .singleton ();
107+ var registry = CrossLayerConstantRegistry .singletonOrNull ();
108+ if (ImageLayerBuildingSupport .buildingImageLayer ()) {
109+ packageManager .initialize (nativeImageSystemClassLoader .defaultSystemClassLoader , registry );
110+ }
111+
112+ if (ImageLayerBuildingSupport .firstImageBuild ()) {
113+ access .registerObjectReplacer (this ::runtimeClassLoaderObjectReplacer );
114+ } else {
115+ var config = (FeatureImpl .DuringSetupAccessImpl ) access ;
116+ config .registerObjectToConstantReplacer (obj -> replaceClassLoadersWithLayerConstant (registry , obj ));
117+ // relink packages defined in the prior layers
118+ config .registerObjectToConstantReplacer (packageManager ::replaceWithPriorLayerPackage );
119+ }
120+ }
121+
122+ @ Override
123+ public void beforeAnalysis (BeforeAnalysisAccess access ) {
124+ var packagesField = ReflectionUtil .lookupField (ClassLoader .class , "packages" );
125+ access .registerFieldValueTransformer (packagesField , new FieldValueTransformerWithAvailability () {
126+
127+ @ Override
128+ public ValueAvailability valueAvailability () {
129+ return ValueAvailability .AfterAnalysis ;
130+ }
131+
132+ @ Override
133+ public Object transform (Object receiver , Object originalValue ) {
134+ assert receiver instanceof ClassLoader : receiver ;
135+ assert originalValue instanceof ConcurrentHashMap : "Underlying representation has changed: " + originalValue ;
136+
137+ /* Retrieving initial package state for this class loader. */
138+ ConcurrentHashMap <String , Package > packages = HostedClassLoaderPackageManagement .singleton ().getRegisteredPackages ((ClassLoader ) receiver );
139+ /* If no package state is available then we must create a clean state. */
140+ return packages == null ? new ConcurrentHashMap <>() : packages ;
141+ }
142+ });
143+
144+ if (ImageLayerBuildingSupport .buildingInitialLayer ()) {
145+ /*
146+ * Note we cannot register these heap constants until the field value transformer has
147+ * been registered. Otherwise there is a race between this feature and
148+ * ObservableImageHeapMapProviderImpl#beforeAnalysis, as during heap scanning all
149+ * fieldValueInterceptors will be computed for the scanned objects.
150+ */
151+ var registry = CrossLayerConstantRegistry .singletonOrNull ();
152+ registry .registerHeapConstant (APP_KEY_NAME , nativeImageSystemClassLoader .defaultSystemClassLoader );
153+ registry .registerHeapConstant (PLATFORM_KEY_NAME , platformClassLoader );
154+ registry .registerHeapConstant (BOOT_KEY_NAME , bootClassLoader );
155+ }
62156 }
63157}
0 commit comments