@@ -122,101 +122,124 @@ private static byte[] generateBytecode(String unsafeNamespace) {
122122 mv .visitMaxs (1 , 1 );
123123 mv .visitEnd ();
124124
125- // main function which accepts a map of class-names to bytecode and returns the defined classes
125+ // main function that accepts a map of class-names to bytecode as well as
126+ // a class-loader or protection-domain, and returns the defined classes
126127 mv = cw .visitMethod (ACC_PUBLIC , "apply" , BIFUNCTION_APPLY_DESCRIPTOR , null , null );
127128
128- Label skipProtectionDomain = new Label ();
129- Label checkBootClassLoader = new Label ();
130- Label hasNextNonBootClass = new Label ();
131- Label classLoaderLocked = new Label ();
132- Label storeNonBootClass = new Label ();
133- Label classLoaderUnlocked = new Label ();
134- Label unlockClassLoaderAndThrow = new Label ();
135- Label setupUnsafeDefiner = new Label ();
136- Label hasNextBootClass = new Label ();
137- Label returnDefinedClasses = new Label ();
129+ // bytecode positions
130+ final Label skipProtectionDomain = new Label ();
131+ final Label checkBootClassLoader = new Label ();
132+ final Label hasNextNonBootClass = new Label ();
133+ final Label classLoaderLocked = new Label ();
134+ final Label storeNonBootClass = new Label ();
135+ final Label classLoaderUnlocked = new Label ();
136+ final Label unlockClassLoaderAndThrow = new Label ();
137+ final Label setupUnsafeDefiner = new Label ();
138+ final Label hasNextBootClass = new Label ();
139+ final Label returnDefinedClasses = new Label ();
140+
141+ // common bytecode variables
142+ final int bytecodeMap = 1 ;
143+ final int protectionDomainOrClassLoader = 2 ;
144+ final int definedClasses = 3 ;
145+ final int mapEntrySetIterator = 4 ;
146+ final int protectionDomain = 5 ;
147+ final int classLoader = 6 ;
148+
149+ // bytecode variables for non-boot classes
150+ final int classLoadingLock = 7 ;
151+ final int bytecodeMapEntry = 8 ;
152+ final int className = 9 ;
153+
154+ // bytecode variables for boot classes
155+ final int unsafeInstance = 7 ;
138156
139157 mv .visitCode ();
140158
141159 // make sure we unlock the class-loader if an exception occurs while defining a class
142160 mv .visitTryCatchBlock (classLoaderLocked , classLoaderUnlocked , unlockClassLoaderAndThrow , null );
143161
162+ // -------- SHARED SETUP CODE --------
163+
144164 // store the defined classes in a list
145165 mv .visitTypeInsn (NEW , "java/util/ArrayList" );
146166 mv .visitInsn (DUP );
147167 mv .visitMethodInsn (INVOKESPECIAL , "java/util/ArrayList" , "<init>" , "()V" , false );
148- mv .visitVarInsn (ASTORE , 3 );
168+ mv .visitVarInsn (ASTORE , definedClasses );
149169
150- // iterate over the map entries
151- mv .visitVarInsn (ALOAD , 1 );
170+ // get entry set iterator from the bytecode map
171+ mv .visitVarInsn (ALOAD , bytecodeMap );
152172 mv .visitMethodInsn (INVOKEINTERFACE , MAP_CLASS , "entrySet" , "()L" + SET_CLASS + ";" , true );
153173 mv .visitMethodInsn (INVOKEINTERFACE , SET_CLASS , "iterator" , "()L" + ITERATOR_CLASS + ";" , true );
154- mv .visitVarInsn (ASTORE , 4 );
174+ mv .visitVarInsn (ASTORE , mapEntrySetIterator );
155175
156- mv .visitVarInsn (ALOAD , 2 );
176+ // check if second argument is a protection domain or class-loader
177+ mv .visitVarInsn (ALOAD , protectionDomainOrClassLoader );
157178 mv .visitTypeInsn (INSTANCEOF , PROTECTIONDOMAIN_CLASS );
158179 mv .visitJumpInsn (IFEQ , skipProtectionDomain );
159180
160181 // extract class-loader from protection domain
161- mv .visitVarInsn (ALOAD , 2 );
182+ mv .visitVarInsn (ALOAD , protectionDomainOrClassLoader );
162183 mv .visitTypeInsn (CHECKCAST , PROTECTIONDOMAIN_CLASS );
163184 mv .visitInsn (DUP );
164- mv .visitVarInsn (ASTORE , 5 );
185+ mv .visitVarInsn (ASTORE , protectionDomain );
165186 mv .visitMethodInsn (
166187 INVOKEVIRTUAL ,
167188 PROTECTIONDOMAIN_CLASS ,
168189 "getClassLoader" ,
169190 "()L" + CLASSLOADER_CLASS + ";" ,
170191 false );
171- mv .visitVarInsn (ASTORE , 6 );
192+ mv .visitVarInsn (ASTORE , classLoader );
172193 mv .visitJumpInsn (GOTO , checkBootClassLoader );
173194
174195 // only have class-loader, no protection domain
175196 mv .visitLabel (skipProtectionDomain );
176197 mv .visitInsn (ACONST_NULL );
177- mv .visitVarInsn (ASTORE , 5 );
178- mv .visitVarInsn (ALOAD , 2 );
198+ mv .visitVarInsn (ASTORE , protectionDomain );
199+ mv .visitVarInsn (ALOAD , protectionDomainOrClassLoader );
179200 mv .visitTypeInsn (CHECKCAST , CLASSLOADER_CLASS );
180- mv .visitVarInsn (ASTORE , 6 );
201+ mv .visitVarInsn (ASTORE , classLoader );
181202
182203 // boot classes can only be defined via Unsafe
183204 mv .visitLabel (checkBootClassLoader );
184- mv .visitVarInsn (ALOAD , 6 );
205+ mv .visitVarInsn (ALOAD , classLoader );
185206 mv .visitJumpInsn (IFNULL , setupUnsafeDefiner );
186207
208+ // -------- LOOP TO DEFINE NON-BOOT CLASSES --------
209+
187210 // check if we've defined all the given bytecode
188211 mv .visitLabel (hasNextNonBootClass );
189- mv .visitVarInsn (ALOAD , 4 );
212+ mv .visitVarInsn (ALOAD , mapEntrySetIterator );
190213 mv .visitMethodInsn (INVOKEINTERFACE , ITERATOR_CLASS , "hasNext" , "()Z" , true );
191214 mv .visitJumpInsn (IFEQ , returnDefinedClasses );
192215
193216 // extract the name of the next class to define
194- mv .visitVarInsn (ALOAD , 4 );
217+ mv .visitVarInsn (ALOAD , mapEntrySetIterator );
195218 mv .visitMethodInsn (INVOKEINTERFACE , ITERATOR_CLASS , "next" , "()L" + OBJECT_CLASS + ";" , true );
196219 mv .visitInsn (DUP );
197- mv .visitVarInsn (ASTORE , 8 );
220+ mv .visitVarInsn (ASTORE , bytecodeMapEntry );
198221 mv .visitMethodInsn (
199222 INVOKEINTERFACE , MAP_ENTRY_CLASS , "getKey" , "()L" + OBJECT_CLASS + ";" , true );
200223 mv .visitTypeInsn (CHECKCAST , STRING_CLASS );
201- mv .visitVarInsn (ASTORE , 9 );
224+ mv .visitVarInsn (ASTORE , className );
202225
203226 // lock the class-loader
204- mv .visitVarInsn (ALOAD , 6 );
205- mv .visitVarInsn (ALOAD , 9 );
227+ mv .visitVarInsn (ALOAD , classLoader );
228+ mv .visitVarInsn (ALOAD , className );
206229 mv .visitMethodInsn (
207230 INVOKEVIRTUAL ,
208231 CLASSLOADER_CLASS ,
209232 "getClassLoadingLock" ,
210233 "(L" + STRING_CLASS + ";)L" + OBJECT_CLASS + ";" ,
211234 false );
212235 mv .visitInsn (DUP );
213- mv .visitVarInsn (ASTORE , 7 );
236+ mv .visitVarInsn (ASTORE , classLoadingLock );
214237 mv .visitInsn (MONITORENTER );
215238 mv .visitLabel (classLoaderLocked );
216239
217240 // check in case the class has already been defined
218- mv .visitVarInsn (ALOAD , 6 );
219- mv .visitVarInsn (ALOAD , 9 );
241+ mv .visitVarInsn (ALOAD , classLoader );
242+ mv .visitVarInsn (ALOAD , className );
220243 mv .visitMethodInsn (
221244 INVOKEVIRTUAL ,
222245 CLASSLOADER_CLASS ,
@@ -228,55 +251,58 @@ private static byte[] generateBytecode(String unsafeNamespace) {
228251
229252 // define the class using the given class-name and bytecode
230253 mv .visitInsn (POP );
231- mv .visitVarInsn (ALOAD , 6 );
232- mv .visitVarInsn (ALOAD , 9 );
233- mv .visitVarInsn (ALOAD , 8 );
254+ mv .visitVarInsn (ALOAD , classLoader );
255+ mv .visitVarInsn (ALOAD , className );
256+ mv .visitVarInsn (ALOAD , bytecodeMapEntry );
234257 mv .visitMethodInsn (
235258 INVOKEINTERFACE , MAP_ENTRY_CLASS , "getValue" , "()L" + OBJECT_CLASS + ";" , true );
236259 mv .visitTypeInsn (CHECKCAST , BYTE_ARRAY );
237260 mv .visitInsn (DUP );
238261 mv .visitInsn (ARRAYLENGTH );
239262 mv .visitInsn (ICONST_0 );
240263 mv .visitInsn (SWAP );
241- mv .visitVarInsn (ALOAD , 5 );
264+ mv .visitVarInsn (ALOAD , protectionDomain );
242265 mv .visitMethodInsn (
243266 INVOKEVIRTUAL , CLASSLOADER_CLASS , "defineClass" , CLASSLOADER_DEFINECLASS_DESCRIPTOR , false );
244267
245268 // store the class in the list whether we defined it or it already existed
246269 mv .visitLabel (storeNonBootClass );
247- mv .visitVarInsn (ALOAD , 3 );
270+ mv .visitVarInsn (ALOAD , definedClasses );
248271 mv .visitInsn (SWAP );
249272 mv .visitMethodInsn (INVOKEVIRTUAL , ARRAYLIST_CLASS , "add" , "(L" + OBJECT_CLASS + ";)Z" , false );
250273 mv .visitInsn (POP );
251274
252275 // unlock the class-loader
253- mv .visitVarInsn (ALOAD , 7 );
276+ mv .visitVarInsn (ALOAD , classLoadingLock );
254277 mv .visitInsn (MONITOREXIT );
255278 mv .visitLabel (classLoaderUnlocked );
256279
280+ // check again if we've defined all the given bytecode
257281 mv .visitJumpInsn (GOTO , hasNextNonBootClass );
258282
259283 // unlock the class-loader if something goes wrong
260284 mv .visitLabel (unlockClassLoaderAndThrow );
261285 mv .visitInsn (DUP );
262- mv .visitVarInsn (ALOAD , 7 );
286+ mv .visitVarInsn (ALOAD , classLoadingLock );
263287 mv .visitInsn (MONITOREXIT );
264288 mv .visitInsn (ATHROW );
265289
290+ // -------- LOOP TO DEFINE BOOT CLASSES --------
291+
266292 // load Unsafe field into local variable for performance
267293 mv .visitLabel (setupUnsafeDefiner );
268294 mv .visitFieldInsn (GETSTATIC , DEFINECLASS_GLUE_CLASS , "UNSAFE" , unsafeDescriptor );
269- mv .visitVarInsn (ASTORE , 7 );
295+ mv .visitVarInsn (ASTORE , unsafeInstance );
270296
271297 // check if we've defined all the given bytecode
272298 mv .visitLabel (hasNextBootClass );
273- mv .visitVarInsn (ALOAD , 4 );
299+ mv .visitVarInsn (ALOAD , mapEntrySetIterator );
274300 mv .visitMethodInsn (INVOKEINTERFACE , ITERATOR_CLASS , "hasNext" , "()Z" , true );
275301 mv .visitJumpInsn (IFEQ , returnDefinedClasses );
276302
277303 // define the class using the given class-name and bytecode
278- mv .visitVarInsn (ALOAD , 7 );
279- mv .visitVarInsn (ALOAD , 4 );
304+ mv .visitVarInsn (ALOAD , unsafeInstance );
305+ mv .visitVarInsn (ALOAD , mapEntrySetIterator );
280306 mv .visitMethodInsn (INVOKEINTERFACE , ITERATOR_CLASS , "next" , "()L" + OBJECT_CLASS + ";" , true );
281307 mv .visitInsn (DUP );
282308 mv .visitMethodInsn (
@@ -291,21 +317,24 @@ private static byte[] generateBytecode(String unsafeNamespace) {
291317 mv .visitInsn (ICONST_0 );
292318 mv .visitInsn (SWAP );
293319 mv .visitInsn (ACONST_NULL );
294- mv .visitVarInsn (ALOAD , 5 );
320+ mv .visitVarInsn (ALOAD , protectionDomain );
295321 mv .visitMethodInsn (
296322 INVOKEVIRTUAL , unsafeClass , "defineClass" , UNSAFE_DEFINECLASS_DESCRIPTOR , false );
297323
298324 // store the class in the list
299- mv .visitVarInsn (ALOAD , 3 );
325+ mv .visitVarInsn (ALOAD , definedClasses );
300326 mv .visitInsn (SWAP );
301327 mv .visitMethodInsn (INVOKEVIRTUAL , ARRAYLIST_CLASS , "add" , "(L" + OBJECT_CLASS + ";)Z" , false );
302328 mv .visitInsn (POP );
303329
330+ // check again if we've defined all the given bytecode
304331 mv .visitJumpInsn (GOTO , hasNextBootClass );
305332
333+ // -------- SHARED RETURN CODE --------
334+
306335 // return the defined classes
307336 mv .visitLabel (returnDefinedClasses );
308- mv .visitVarInsn (ALOAD , 3 );
337+ mv .visitVarInsn (ALOAD , definedClasses );
309338 mv .visitInsn (ARETURN );
310339
311340 mv .visitMaxs (-1 , -1 );
0 commit comments