2525import java .lang .invoke .MethodHandles ;
2626import java .lang .invoke .MethodType ;
2727import java .util .Collection ;
28+ import java .util .Map ;
2829import java .util .Objects ;
30+ import java .util .Optional ;
2931import java .util .concurrent .CancellationException ;
3032import java .util .concurrent .CompletableFuture ;
33+ import java .util .concurrent .ConcurrentHashMap ;
3134import java .util .concurrent .ExecutionException ;
3235import java .util .function .Function ;
3336import org .apache .ignite .internal .lang .IgniteExceptionMapperUtil ;
3942 * Table view utilities.
4043 */
4144public final class ViewUtils {
45+ private static final Map <Class <?>, Optional <MethodHandle >> COPY_FACTORY_METHOD_CACHE = new ConcurrentHashMap <>();
46+
4247 /**
4348 * Waits for async operation completion.
4449 *
@@ -92,19 +97,16 @@ public static Throwable ensurePublicException(Throwable e) {
9297 // TODO: consider removing after IGNITE-22721 gets resolved.
9398 private static <T extends Throwable & TraceableException > Throwable copyExceptionWithCauseIfPossible (T e ) {
9499 // Copy exception with cause does not respect custom exception fields.
95- // We should just create this during compile time and call it a day, or at least cache this. Create ticket.
96- try {
97- Class <T > klass = (Class <T >) e .getClass ();
98- MethodHandles .Lookup privateLookup = MethodHandles .privateLookupIn (klass , MethodHandles .lookup ());
99- MethodHandle mhandle = privateLookup .findStatic (
100- klass ,
101- "copy" ,
102- MethodType .methodType (klass , klass ) // adjust signature
103- );
104-
105- return (T ) mhandle .invoke (e );
106- } catch (Throwable ignored ) {
107- // Intentionally left blank.
100+ // TODO: IGNITE-28422 We should just create this during compile time and call it a day
101+ Optional <MethodHandle > copyMethodHandleOpt = COPY_FACTORY_METHOD_CACHE .computeIfAbsent (e .getClass (),
102+ ViewUtils ::createMethodHandleForCopy );
103+
104+ if (copyMethodHandleOpt .isPresent ()) {
105+ try {
106+ return (T ) copyMethodHandleOpt .get ().invoke (e );
107+ } catch (Throwable ignored ) {
108+ // Intentionally left blank.
109+ }
108110 }
109111
110112 Throwable copy = ExceptionUtils .copyExceptionWithCause (e .getClass (), e .traceId (), e .code (), e .getMessage (), e .getCause ());
@@ -116,6 +118,21 @@ private static <T extends Throwable & TraceableException> Throwable copyExceptio
116118 + e .getClass ().getName (), e );
117119 }
118120
121+ private static Optional <MethodHandle > createMethodHandleForCopy (Class <?> type ) {
122+ try {
123+ MethodHandles .Lookup privateLookup = MethodHandles .privateLookupIn (type , MethodHandles .lookup ());
124+ MethodHandle mhandle = privateLookup .findStatic (
125+ type ,
126+ "copy" ,
127+ MethodType .methodType (type , type ) // adjust signature
128+ );
129+
130+ return Optional .of (mhandle );
131+ } catch (IllegalAccessException | NoSuchMethodException ignored ) {
132+ return Optional .empty ();
133+ }
134+ }
135+
119136 /**
120137 * Checks that given keys collection isn't null and there is no a null-value key.
121138 *
0 commit comments