|
40 | 40 |
|
41 | 41 | import org.graalvm.nativeimage.hosted.RuntimeReflection; |
42 | 42 |
|
| 43 | +import com.oracle.graal.pointsto.heap.ImageHeapScanner; |
43 | 44 | import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; |
44 | 45 | import com.oracle.graal.pointsto.meta.AnalysisType; |
45 | 46 | import com.oracle.svm.core.SubstrateOptions; |
|
48 | 49 | import com.oracle.svm.core.fieldvaluetransformer.FieldValueTransformerWithAvailability; |
49 | 50 | import com.oracle.svm.core.invoke.MethodHandleIntrinsic; |
50 | 51 | import com.oracle.svm.core.util.VMError; |
51 | | -import com.oracle.svm.hosted.FeatureImpl; |
| 52 | +import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; |
52 | 53 | import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl; |
53 | 54 | import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; |
54 | 55 | import com.oracle.svm.util.ReflectionUtil; |
@@ -157,7 +158,9 @@ public void duringSetup(DuringSetupAccess access) { |
157 | 158 | } |
158 | 159 |
|
159 | 160 | @Override |
160 | | - public void beforeAnalysis(BeforeAnalysisAccess access) { |
| 161 | + public void beforeAnalysis(BeforeAnalysisAccess a) { |
| 162 | + var access = (BeforeAnalysisAccessImpl) a; |
| 163 | + |
161 | 164 | /* java.lang.invoke functions called through reflection */ |
162 | 165 | Class<?> mhImplClazz = access.findClassByName("java.lang.invoke.MethodHandleImpl"); |
163 | 166 |
|
@@ -200,7 +203,9 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { |
200 | 203 | access.registerSubtypeReachabilityHandler(MethodHandleFeature::scanBoundMethodHandle, |
201 | 204 | access.findClassByName("java.lang.invoke.BoundMethodHandle")); |
202 | 205 |
|
203 | | - AnalysisMetaAccess metaAccess = ((FeatureImpl.BeforeAnalysisAccessImpl) access).getMetaAccess(); |
| 206 | + AnalysisMetaAccess metaAccess = access.getMetaAccess(); |
| 207 | + ImageHeapScanner heapScanner = access.getUniverse().getHeapScanner(); |
| 208 | + |
204 | 209 | access.registerFieldValueTransformer( |
205 | 210 | ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer"), "cache"), |
206 | 211 | new FieldValueTransformerWithAvailability() { |
@@ -241,6 +246,37 @@ private boolean isSpeciesReachable(Object speciesData) { |
241 | 246 | access.registerFieldValueTransformer( |
242 | 247 | ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.MethodType"), "internTable"), |
243 | 248 | (receiver, originalValue) -> runtimeMethodTypeInternTable); |
| 249 | + |
| 250 | + /* |
| 251 | + * SpeciesData.transformHelpers is a lazily initialized cache of MethodHandle objects. We do |
| 252 | + * not want to make a MethodHandle reachable just because the image builder initialized the |
| 253 | + * cache, so we filter out unreachable objects. This also solves the problem when late image |
| 254 | + * heap re-scanning after static analysis would see a method handle that was not yet cached |
| 255 | + * during static analysis, in which case image building would fail because new types would |
| 256 | + * be made reachable after analysis. |
| 257 | + */ |
| 258 | + access.registerFieldValueTransformer( |
| 259 | + ReflectionUtil.lookupField(ReflectionUtil.lookupClass(false, "java.lang.invoke.ClassSpecializer$SpeciesData"), "transformHelpers"), |
| 260 | + new FieldValueTransformerWithAvailability() { |
| 261 | + @Override |
| 262 | + public FieldValueTransformerWithAvailability.ValueAvailability valueAvailability() { |
| 263 | + return FieldValueTransformerWithAvailability.ValueAvailability.AfterAnalysis; |
| 264 | + } |
| 265 | + |
| 266 | + @Override |
| 267 | + @SuppressWarnings("unchecked") |
| 268 | + public Object transform(Object receiver, Object originalValue) { |
| 269 | + MethodHandle[] originalArray = (MethodHandle[]) originalValue; |
| 270 | + MethodHandle[] filteredArray = new MethodHandle[originalArray.length]; |
| 271 | + for (int i = 0; i < originalArray.length; i++) { |
| 272 | + MethodHandle handle = originalArray[i]; |
| 273 | + if (handle != null && heapScanner.isObjectReachable(handle)) { |
| 274 | + filteredArray[i] = handle; |
| 275 | + } |
| 276 | + } |
| 277 | + return filteredArray; |
| 278 | + } |
| 279 | + }); |
244 | 280 | } |
245 | 281 |
|
246 | 282 | private static void registerMHImplFunctionsForReflection(DuringAnalysisAccess access) { |
|
0 commit comments