@@ -166,6 +166,7 @@ private static byte[] generateBytecode(String unsafeNamespace) {
166166 final Label unlockClassLoaderAndThrow = new Label ();
167167 final Label setupUnsafeDefiner = new Label ();
168168 final Label hasNextBootClass = new Label ();
169+ final Label storeBootClass = new Label ();
169170 final Label returnDefinedClasses = new Label ();
170171
171172 // common bytecode variables
@@ -175,14 +176,14 @@ private static byte[] generateBytecode(String unsafeNamespace) {
175176 final int mapEntrySetIterator = 4 ;
176177 final int protectionDomain = 5 ;
177178 final int classLoader = 6 ;
179+ final int className = 7 ;
178180
179181 // bytecode variables for non-boot classes
180- final int classLoadingLock = 7 ;
181- final int bytecodeMapEntry = 8 ;
182- final int className = 9 ;
182+ final int classLoadingLock = 8 ;
183+ final int bytecodeMapEntry = 9 ;
183184
184185 // bytecode variables for boot classes
185- final int unsafeInstance = 7 ;
186+ final int unsafeInstance = 8 ;
186187
187188 mv .visitCode ();
188189
@@ -278,11 +279,13 @@ private static byte[] generateBytecode(String unsafeNamespace) {
278279 false );
279280 mv .visitInsn (DUP );
280281 mv .visitJumpInsn (IFNONNULL , storeNonBootClass );
281-
282- // define the class using the given class-name and bytecode
283282 mv .visitInsn (POP );
283+
284+ // not yet defined, prepare arguments to define it
284285 mv .visitVarInsn (ALOAD , classLoader );
285286 mv .visitVarInsn (ALOAD , className );
287+
288+ // extract the bytecode of the next class to define
286289 mv .visitVarInsn (ALOAD , bytecodeMapEntry );
287290 mv .visitMethodInsn (
288291 INVOKEINTERFACE , MAP_ENTRY_CLASS , "getValue" , "()L" + OBJECT_CLASS + ";" , true );
@@ -291,7 +294,10 @@ private static byte[] generateBytecode(String unsafeNamespace) {
291294 mv .visitInsn (ARRAYLENGTH );
292295 mv .visitInsn (ICONST_0 );
293296 mv .visitInsn (SWAP );
297+
294298 mv .visitVarInsn (ALOAD , protectionDomain );
299+
300+ // define the class using the given class-name and bytecode
295301 mv .visitMethodInsn (
296302 INVOKEVIRTUAL , CLASSLOADER_CLASS , "defineClass" , CLASSLOADER_DEFINECLASS_DESCRIPTOR , false );
297303
@@ -329,28 +335,37 @@ private static byte[] generateBytecode(String unsafeNamespace) {
329335 mv .visitMethodInsn (INVOKEINTERFACE , ITERATOR_CLASS , "hasNext" , "()Z" , true );
330336 mv .visitJumpInsn (IFEQ , returnDefinedClasses );
331337
332- // define the class using the given class-name and bytecode
333338 mv .visitVarInsn (ALOAD , unsafeInstance );
339+
340+ // extract the name of the next class to define
334341 mv .visitVarInsn (ALOAD , mapEntrySetIterator );
335342 mv .visitMethodInsn (INVOKEINTERFACE , ITERATOR_CLASS , "next" , "()L" + OBJECT_CLASS + ";" , true );
336343 mv .visitInsn (DUP );
337344 mv .visitMethodInsn (
338345 INVOKEINTERFACE , MAP_ENTRY_CLASS , "getKey" , "()L" + OBJECT_CLASS + ";" , true );
339346 mv .visitTypeInsn (CHECKCAST , STRING_CLASS );
347+ mv .visitInsn (DUP );
348+ mv .visitVarInsn (ASTORE , className );
340349 mv .visitInsn (SWAP );
350+
351+ // extract the bytecode of the next class to define
341352 mv .visitMethodInsn (
342353 INVOKEINTERFACE , MAP_ENTRY_CLASS , "getValue" , "()L" + OBJECT_CLASS + ";" , true );
343354 mv .visitTypeInsn (CHECKCAST , BYTE_ARRAY );
344355 mv .visitInsn (DUP );
345356 mv .visitInsn (ARRAYLENGTH );
346357 mv .visitInsn (ICONST_0 );
347358 mv .visitInsn (SWAP );
359+
348360 mv .visitInsn (ACONST_NULL );
349361 mv .visitVarInsn (ALOAD , protectionDomain );
362+
363+ // define the boot class using the given class-name and bytecode
350364 mv .visitMethodInsn (
351365 INVOKEVIRTUAL , unsafeClass , "defineClass" , UNSAFE_DEFINECLASS_DESCRIPTOR , false );
352366
353367 // store the class in the list
368+ mv .visitLabel (storeBootClass );
354369 mv .visitVarInsn (ALOAD , definedClasses );
355370 mv .visitInsn (SWAP );
356371 mv .visitMethodInsn (INVOKEVIRTUAL , ARRAYLIST_CLASS , "add" , "(L" + OBJECT_CLASS + ";)Z" , false );
0 commit comments