Skip to content

Commit 5849301

Browse files
committed
Adapt JDK-8358426 for Web Image: Improve lazy computation in Locale
The cache fields were moved and now use StableValue.supplier
1 parent a9d7a4b commit 5849301

File tree

3 files changed

+64
-30
lines changed

3 files changed

+64
-30
lines changed

web-image/mx.web-image/suite.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@
185185
"java.compiler",
186186
],
187187
"requiresConcealed": {
188-
"java.base": ["sun.nio.ch", "sun.security.provider", "jdk.internal.reflect"],
188+
"java.base": [
189+
"sun.nio.ch",
190+
"sun.security.provider",
191+
"jdk.internal.reflect",
192+
],
189193
"jdk.internal.vm.ci": ["jdk.vm.ci.code.site", "jdk.vm.ci.code", "jdk.vm.ci.common", "jdk.vm.ci.meta"],
190194
},
191195
"javaCompliance": "21+",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.oracle.svm.hosted.webimage;
27+
28+
import java.lang.reflect.Method;
29+
import java.util.function.Supplier;
30+
31+
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
32+
33+
import com.oracle.svm.util.ReflectionUtil;
34+
35+
/**
36+
* Field value transformer that creates a new StableSupplier with the same {@link Supplier} as the
37+
* original that was not initialized yet.
38+
* <p>
39+
* This can be used to reset caches that are based on stable value suppliers.
40+
* <p>
41+
* Uses reflection because StableSupplier is from JDK25 and proguard does not yet support class
42+
* files from that version.
43+
*/
44+
public final class ResetStableSupplierTransformer implements FieldValueTransformer {
45+
@Override
46+
public Object transform(Object receiver, Object originalValue) {
47+
Class<?> stableSupplierClass = ReflectionUtil.lookupClass("jdk.internal.lang.stable.StableSupplier");
48+
Method stableSupplierOf = ReflectionUtil.lookupMethod(stableSupplierClass, "of", Supplier.class);
49+
Method stableSupplierOriginal = ReflectionUtil.lookupMethod(stableSupplierClass, "original");
50+
Object originalSupplier = ReflectionUtil.invokeMethod(stableSupplierOriginal, originalValue);
51+
return ReflectionUtil.invokeMethod(stableSupplierOf, null, originalSupplier);
52+
}
53+
}

web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import java.util.List;
3636
import java.util.Map;
3737
import java.util.function.Predicate;
38-
import java.util.function.Supplier;
3938

4039
import org.graalvm.nativeimage.AnnotationAccess;
4140
import org.graalvm.nativeimage.ImageSingletons;
@@ -189,35 +188,12 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
189188
*
190189
* These caches can contribute ~1MB to the image size, clearing them avoids this overhead at
191190
* the cost of having to recreate the Locale and BaseLocale objects once when they're
192-
* requested.
193-
*
194-
* On JDK21, ReferencedKeySet and ReferencedKeyMap don't exist. We have to go through
195-
* reflection to access them because analysis tools like spotbugs still run on JDK21
191+
* requested at run-time.
196192
*/
197-
Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale$1InterningCache", "CACHE");
198-
Field localeCacheField = accessImpl.findField("java.util.Locale$LocaleCache", "LOCALE_CACHE");
199-
200-
access.registerFieldValueTransformer(baseLocaleCacheField, (receiver, originalValue) -> {
201-
/*
202-
* Executes `ReferencedKeySet.create(true,
203-
* ReferencedKeySet.concurrentHashMapSupplier())` with reflection.
204-
*/
205-
Class<?> referencedKeySetClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet");
206-
Method createMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "create", boolean.class, Supplier.class);
207-
Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "concurrentHashMapSupplier");
208-
return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null));
209-
});
210-
211-
access.registerFieldValueTransformer(localeCacheField, (receiver, originalValue) -> {
212-
/*
213-
* Executes `ReferencedKeyMap.create(true,
214-
* ReferencedKeyMap.concurrentHashMapSupplier())` with reflection.
215-
*/
216-
Class<?> referencedKeyMapClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeyMap");
217-
Method createMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "create", boolean.class, Supplier.class);
218-
Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "concurrentHashMapSupplier");
219-
return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null));
220-
});
193+
Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale", "CACHE");
194+
Field localeCacheField = accessImpl.findField("java.util.Locale", "LOCALE_CACHE");
195+
access.registerFieldValueTransformer(baseLocaleCacheField, new ResetStableSupplierTransformer());
196+
access.registerFieldValueTransformer(localeCacheField, new ResetStableSupplierTransformer());
221197
}
222198

223199
@Override
@@ -341,4 +317,5 @@ private boolean neverInlineTrivial(@SuppressWarnings("unused") AnalysisMethod ca
341317
*/
342318
return AnnotationAccess.isAnnotationPresent(callee, JS.class);
343319
}
320+
344321
}

0 commit comments

Comments
 (0)