@@ -154,17 +154,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
154154 access .registerReachabilityHandler (MethodHandleFeature ::registerInvokersFunctionsForReflection ,
155155 ReflectionUtil .lookupMethod (access .findClassByName ("java.lang.invoke.Invokers" ), "getFunction" , byte .class ));
156156
157- access .registerReachabilityHandler (MethodHandleFeature ::registerValueConversionBoxFunctionsForReflection ,
158- ReflectionUtil .lookupMethod (ValueConversions .class , "boxExact" , Wrapper .class ));
159-
160- access .registerReachabilityHandler (MethodHandleFeature ::registerValueConversionUnboxFunctionsForReflection ,
161- ReflectionUtil .lookupMethod (ValueConversions .class , "unbox" , Wrapper .class , int .class ));
162-
163- access .registerReachabilityHandler (MethodHandleFeature ::registerValueConversionConvertFunctionsForReflection ,
164- ReflectionUtil .lookupMethod (ValueConversions .class , "convertPrimitive" , Wrapper .class , Wrapper .class ));
165-
166- access .registerReachabilityHandler (MethodHandleFeature ::registerValueConversionIgnoreForReflection ,
167- ReflectionUtil .lookupMethod (ValueConversions .class , "ignore" ));
157+ eagerlyInitializeValueConversionsCaches ();
168158
169159 access .registerClassInitializerReachabilityHandler (MethodHandleFeature ::registerDelegatingMHFunctionsForReflection ,
170160 access .findClassByName ("java.lang.invoke.DelegatingMethodHandle" ));
@@ -263,44 +253,32 @@ private static void registerInvokersFunctionsForReflection(DuringAnalysisAccess
263253 RuntimeReflection .register (ReflectionUtil .lookupMethod (invokersClazz , "directVarHandleTarget" , access .findClassByName ("java.lang.invoke.VarHandle" )));
264254 }
265255
266- private static void registerValueConversionBoxFunctionsForReflection ( DuringAnalysisAccess access ) {
267- for ( Wrapper type : Wrapper . values ()) {
268- if ( type . primitiveType (). isPrimitive () && type != Wrapper . VOID ) {
269- RuntimeReflection . register ( ReflectionUtil . lookupMethod ( ValueConversions . class , "box" + type . wrapperSimpleName (), type . primitiveType ()));
270- }
271- }
272- }
256+ /**
257+ * Eagerly initialize method handle caches in {@link ValueConversions} so that 1) we avoid
258+ * reflection registration for conversion methods, and 2) the static analysis already sees a
259+ * consistent snapshot that does not change after analysis when the JDK needs more conversions.
260+ */
261+ private static void eagerlyInitializeValueConversionsCaches () {
262+ ValueConversions . ignore ();
273263
274- private static void registerValueConversionUnboxFunctionsForReflection (DuringAnalysisAccess access ) {
275- for (Wrapper type : Wrapper .values ()) {
276- if (type .primitiveType ().isPrimitive () && type != Wrapper .VOID ) {
277- RuntimeReflection .register (ReflectionUtil .lookupMethod (ValueConversions .class , "unbox" + type .wrapperSimpleName (), type .wrapperType ()));
278- RuntimeReflection .register (ReflectionUtil .lookupMethod (ValueConversions .class , "unbox" + type .wrapperSimpleName (), Object .class , boolean .class ));
264+ for (Wrapper src : Wrapper .values ()) {
265+ if (src != Wrapper .VOID && src .primitiveType ().isPrimitive ()) {
266+ ValueConversions .boxExact (src );
267+
268+ ValueConversions .unboxExact (src , false );
269+ ValueConversions .unboxExact (src , true );
270+ ValueConversions .unboxWiden (src );
271+ ValueConversions .unboxCast (src );
279272 }
280- }
281- }
282273
283- private static void registerValueConversionConvertFunctionsForReflection (DuringAnalysisAccess access ) {
284- for (Wrapper src : Wrapper .values ()) {
285- for (Wrapper dest : Wrapper .values ()) {
286- if (src != dest && src .primitiveType ().isPrimitive () && src != Wrapper .VOID && dest .primitiveType ().isPrimitive () && dest != Wrapper .VOID ) {
287- RuntimeReflection .register (ReflectionUtil .lookupMethod (ValueConversions .class , valueConverterName (src , dest ), src .primitiveType ()));
274+ for (Wrapper dst : Wrapper .values ()) {
275+ if (src != Wrapper .VOID && dst != Wrapper .VOID && (src == dst || (src .primitiveType ().isPrimitive () && dst .primitiveType ().isPrimitive ()))) {
276+ ValueConversions .convertPrimitive (src , dst );
288277 }
289278 }
290279 }
291280 }
292281
293- private static String valueConverterName (Wrapper src , Wrapper dest ) {
294- String srcType = src .primitiveSimpleName ();
295- String destType = dest .primitiveSimpleName ();
296- /* Capitalize first letter of destination type */
297- return srcType + "To" + destType .substring (0 , 1 ).toUpperCase () + destType .substring (1 );
298- }
299-
300- private static void registerValueConversionIgnoreForReflection (DuringAnalysisAccess access ) {
301- RuntimeReflection .register (ReflectionUtil .lookupMethod (ValueConversions .class , "ignore" , Object .class ));
302- }
303-
304282 private static void registerDelegatingMHFunctionsForReflection (DuringAnalysisAccess access ) {
305283 Class <?> delegatingMHClazz = access .findClassByName ("java.lang.invoke.DelegatingMethodHandle" );
306284 RuntimeReflection .register (ReflectionUtil .lookupMethod (delegatingMHClazz , "getTarget" ));
0 commit comments