2828import java .util .Map ;
2929import java .util .Set ;
3030import java .util .concurrent .ConcurrentHashMap ;
31+ import java .util .function .Supplier ;
3132import javax .annotation .Nullable ;
3233import net .bytebuddy .agent .builder .AgentBuilder .Transformer ;
3334import net .bytebuddy .description .type .TypeDescription ;
@@ -88,7 +89,7 @@ Class<?> inject(ClassLoader classLoader, String className) {
8889 private final List <HelperResource > helperResources ;
8990 @ Nullable private final ClassLoader helpersSource ;
9091 @ Nullable private final Instrumentation instrumentation ;
91- private final Map <String , byte []> dynamicTypeMap = new LinkedHashMap <>();
92+ private final Map <String , Supplier < byte []> > dynamicTypeMap = new LinkedHashMap <>();
9293
9394 private final Cache <ClassLoader , Boolean > injectedClassLoaders = Cache .weak ();
9495 private final Cache <ClassLoader , Boolean > resourcesInjectedClassLoaders = Cache .weak ();
@@ -108,7 +109,6 @@ public HelperInjector(
108109 String requestingName ,
109110 List <String > helperClassNames ,
110111 List <HelperResource > helperResources ,
111- // TODO can this be replaced with the context class loader?
112112 ClassLoader helpersSource ,
113113 Instrumentation instrumentation ) {
114114 this .requestingName = requestingName ;
@@ -120,7 +120,9 @@ public HelperInjector(
120120 }
121121
122122 private HelperInjector (
123- String requestingName , Map <String , byte []> helperMap , Instrumentation instrumentation ) {
123+ String requestingName ,
124+ Map <String , Supplier <byte []>> helperMap ,
125+ Instrumentation instrumentation ) {
124126 this .requestingName = requestingName ;
125127
126128 this .helperClassNames = helperMap .keySet ();
@@ -135,9 +137,9 @@ public static HelperInjector forDynamicTypes(
135137 String requestingName ,
136138 Collection <DynamicType .Unloaded <?>> helpers ,
137139 Instrumentation instrumentation ) {
138- Map <String , byte []> bytes = new HashMap <>(helpers .size ());
140+ Map <String , Supplier < byte []> > bytes = new HashMap <>(helpers .size ());
139141 for (DynamicType .Unloaded <?> helper : helpers ) {
140- bytes .put (helper .getTypeDescription ().getName (), helper . getBytes () );
142+ bytes .put (helper .getTypeDescription ().getName (), helper :: getBytes );
141143 }
142144 return new HelperInjector (requestingName , bytes , instrumentation );
143145 }
@@ -146,18 +148,27 @@ public static void setHelperInjectorListener(HelperInjectorListener listener) {
146148 helperInjectorListener = listener ;
147149 }
148150
149- private Map <String , byte []> getHelperMap () throws IOException {
151+ private Map <String , Supplier < byte []>> getHelperMap () {
150152 if (dynamicTypeMap .isEmpty ()) {
151- Map <String , byte []> classnameToBytes = new LinkedHashMap <>();
152-
153- ClassFileLocator locator = ClassFileLocator .ForClassLoader .of (helpersSource );
153+ Map <String , Supplier <byte []>> result = new LinkedHashMap <>();
154154
155155 for (String helperClassName : helperClassNames ) {
156- byte [] classBytes = locator .locate (helperClassName ).resolve ();
157- classnameToBytes .put (helperClassName , classBytes );
156+ result .put (
157+ helperClassName ,
158+ () -> {
159+ try (ClassFileLocator locator = ClassFileLocator .ForClassLoader .of (helpersSource )) {
160+ return locator .locate (helperClassName ).resolve ();
161+ } catch (IOException exception ) {
162+ if (logger .isLoggable (SEVERE )) {
163+ logger .log (
164+ SEVERE , "Failed to read {0}" , new Object [] {helperClassName }, exception );
165+ }
166+ throw new IllegalStateException ("Failed to read " + helperClassName , exception );
167+ }
168+ });
158169 }
159170
160- return classnameToBytes ;
171+ return result ;
161172 } else {
162173 return dynamicTypeMap ;
163174 }
@@ -248,10 +259,10 @@ private void injectHelperClasses(TypeDescription typeDescription, ClassLoader cl
248259 new Object [] {cl , helperClassNames });
249260 }
250261
251- Map <String , byte []> classnameToBytes = getHelperMap ();
262+ Map <String , Supplier < byte []> > classnameToBytes = getHelperMap ();
252263 Map <String , HelperClassInjector > map =
253264 helperInjectors .computeIfAbsent (cl , (unused ) -> new ConcurrentHashMap <>());
254- for (Map .Entry <String , byte []> entry : classnameToBytes .entrySet ()) {
265+ for (Map .Entry <String , Supplier < byte []> > entry : classnameToBytes .entrySet ()) {
255266 // for boot loader we use a placeholder injector, we only need these classes to be
256267 // in the injected classes map to later tell which of the classes are injected
257268 HelperClassInjector injector =
@@ -280,9 +291,18 @@ private void injectHelperClasses(TypeDescription typeDescription, ClassLoader cl
280291 });
281292 }
282293
283- private Map <String , Class <?>> injectBootstrapClassLoader (Map <String , byte []> classnameToBytes )
294+ private static Map <String , byte []> resolve (Map <String , Supplier <byte []>> classes ) {
295+ Map <String , byte []> result = new LinkedHashMap <>();
296+ for (Map .Entry <String , Supplier <byte []>> entry : classes .entrySet ()) {
297+ result .put (entry .getKey (), entry .getValue ().get ());
298+ }
299+ return result ;
300+ }
301+
302+ private Map <String , Class <?>> injectBootstrapClassLoader (Map <String , Supplier <byte []>> inject )
284303 throws IOException {
285304
305+ Map <String , byte []> classnameToBytes = resolve (inject );
286306 if (helperInjectorListener != null ) {
287307 helperInjectorListener .onInjection (classnameToBytes );
288308 }
@@ -358,16 +378,16 @@ public static Class<?> loadHelperClass(ClassLoader classLoader, String className
358378 }
359379
360380 private static class HelperClassInjector {
361- private final byte [] bytes ;
381+ private final Supplier < byte []> bytes ;
362382
363- HelperClassInjector (byte [] bytes ) {
383+ HelperClassInjector (Supplier < byte []> bytes ) {
364384 this .bytes = bytes ;
365385 }
366386
367387 Class <?> inject (ClassLoader classLoader , String className ) {
368388 Map <String , Class <?>> result =
369389 new ClassInjector .UsingReflection (classLoader )
370- .injectRaw (Collections .singletonMap (className , bytes ));
390+ .injectRaw (Collections .singletonMap (className , bytes . get () ));
371391 return result .get (className );
372392 }
373393 }
0 commit comments