@@ -169,74 +169,13 @@ public void visitCode() {
169169 mv .visitJumpInsn (IFEQ , notDatadogGlueRequest );
170170
171171 if (JVM .atLeastJava (15 )) {
172- // on Java 15+ prepare MethodHandles.lookup()
173- mv .visitMethodInsn (
174- INVOKESTATIC ,
175- "java/lang/invoke/MethodHandles" ,
176- "lookup" ,
177- "()Ljava/lang/invoke/MethodHandles$Lookup;" ,
178- false );
179- mv .visitLdcInsn (DefineClassGlue .V9 );
172+ defineClassUsingMethodHandles ();
180173 } else if (JVM .atLeastJava (9 )) {
181174 // on Java 9+ prepare jdk.internal.misc.Unsafe
182- mv .visitMethodInsn (
183- INVOKESTATIC ,
184- "jdk/internal/misc/Unsafe" ,
185- "getUnsafe" ,
186- "()Ljdk/internal/misc/Unsafe;" ,
187- false );
188- mv .visitLdcInsn (Type .getType (ClassLoader .class ));
189- mv .visitLdcInsn (DefineClassGlue .V9 );
175+ defineClassUsingUnsafe ("jdk/internal/misc/Unsafe" , DefineClassGlue .V9 );
190176 } else {
191177 // on Java 8 prepare sun.misc.Unsafe
192- mv .visitMethodInsn (
193- INVOKESTATIC , "sun/misc/Unsafe" , "getUnsafe" , "()Lsun/misc/Unsafe;" , false );
194- mv .visitLdcInsn (Type .getType (ClassLoader .class ));
195- mv .visitLdcInsn (DefineClassGlue .V8 );
196- }
197-
198- // unpack the UTF-16BE encoded string back into bytecode
199- mv .visitFieldInsn (
200- GETSTATIC , "java/nio/charset/StandardCharsets" , "UTF_16BE" , "Ljava/nio/charset/Charset;" );
201- mv .visitMethodInsn (
202- INVOKEVIRTUAL , "java/lang/String" , "getBytes" , "(Ljava/nio/charset/Charset;)[B" , false );
203-
204- if (JVM .atLeastJava (15 )) {
205- // on Java 15+ use MethodHandles.lookup().defineHiddenClass(...)
206- mv .visitInsn (ICONST_0 );
207- mv .visitInsn (ICONST_0 );
208- mv .visitTypeInsn (ANEWARRAY , "java/lang/invoke/MethodHandles$Lookup$ClassOption" );
209- mv .visitMethodInsn (
210- INVOKEVIRTUAL ,
211- "java/lang/invoke/MethodHandles$Lookup" ,
212- "defineHiddenClass" ,
213- "([BZ[Ljava/lang/invoke/MethodHandles$Lookup$ClassOption;)Ljava/lang/invoke/MethodHandles$Lookup;" ,
214- false );
215- // use lookupClass() to retrieve the hidden class we just defined
216- mv .visitMethodInsn (
217- INVOKEVIRTUAL ,
218- "java/lang/invoke/MethodHandles$Lookup" ,
219- "lookupClass" ,
220- "()Ljava/lang/Class;" ,
221- false );
222- } else if (JVM .atLeastJava (9 )) {
223- // on Java 9+ use jdk.internal.misc.Unsafe.defineAnonymousClass(...)
224- mv .visitInsn (ACONST_NULL );
225- mv .visitMethodInsn (
226- INVOKEVIRTUAL ,
227- "jdk/internal/misc/Unsafe" ,
228- "defineAnonymousClass" ,
229- "(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;" ,
230- false );
231- } else {
232- // on Java 8 use sun.misc.Unsafe.defineAnonymousClass(...)
233- mv .visitInsn (ACONST_NULL );
234- mv .visitMethodInsn (
235- INVOKEVIRTUAL ,
236- "sun/misc/Unsafe" ,
237- "defineAnonymousClass" ,
238- "(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;" ,
239- false );
178+ defineClassUsingUnsafe ("sun/misc/Unsafe" , DefineClassGlue .V8 );
240179 }
241180
242181 mv .visitInsn (ARETURN );
@@ -246,6 +185,65 @@ public void visitCode() {
246185 mv .visitFrame (F_SAME , 0 , null , 0 , null );
247186 }
248187
188+ private void defineClassUsingMethodHandles () {
189+ // on Java 15+ prepare MethodHandles.lookup()
190+ mv .visitMethodInsn (
191+ INVOKESTATIC ,
192+ "java/lang/invoke/MethodHandles" ,
193+ "lookup" ,
194+ "()Ljava/lang/invoke/MethodHandles$Lookup;" ,
195+ false );
196+ mv .visitLdcInsn (DefineClassGlue .V9 );
197+ unpackByteCode ();
198+ // on Java 15+ use MethodHandles.lookup().defineHiddenClass(...)
199+ mv .visitInsn (ICONST_0 );
200+ mv .visitInsn (ICONST_0 );
201+ mv .visitTypeInsn (ANEWARRAY , "java/lang/invoke/MethodHandles$Lookup$ClassOption" );
202+ mv .visitMethodInsn (
203+ INVOKEVIRTUAL ,
204+ "java/lang/invoke/MethodHandles$Lookup" ,
205+ "defineHiddenClass" ,
206+ "([BZ[Ljava/lang/invoke/MethodHandles$Lookup$ClassOption;)Ljava/lang/invoke/MethodHandles$Lookup;" ,
207+ false );
208+ // use lookupClass() to retrieve the hidden class we just defined
209+ mv .visitMethodInsn (
210+ INVOKEVIRTUAL ,
211+ "java/lang/invoke/MethodHandles$Lookup" ,
212+ "lookupClass" ,
213+ "()Ljava/lang/Class;" ,
214+ false );
215+ }
216+
217+ private void defineClassUsingUnsafe (String owner , String glue ) {
218+ String descriptor = "()L" +owner +";" ;
219+ // on Java 9+ prepare jdk.internal.misc.Unsafe
220+ mv .visitMethodInsn (
221+ INVOKESTATIC ,
222+ owner ,
223+ "getUnsafe" ,
224+ descriptor ,
225+ false );
226+ mv .visitLdcInsn (Type .getType (ClassLoader .class ));
227+ mv .visitLdcInsn (glue );
228+ unpackByteCode ();
229+ // on Java 9+ use jdk.internal.misc.Unsafe.defineAnonymousClass(...)
230+ mv .visitInsn (ACONST_NULL );
231+ mv .visitMethodInsn (
232+ INVOKEVIRTUAL ,
233+ owner ,
234+ "defineAnonymousClass" ,
235+ "(Ljava/lang/Class;[B[Ljava/lang/Object;)Ljava/lang/Class;" ,
236+ false );
237+ }
238+
239+ private void unpackByteCode () {
240+ // unpack the UTF-16BE encoded string back into bytecode
241+ mv .visitFieldInsn (
242+ GETSTATIC , "java/nio/charset/StandardCharsets" , "UTF_16BE" , "Ljava/nio/charset/Charset;" );
243+ mv .visitMethodInsn (
244+ INVOKEVIRTUAL , "java/lang/String" , "getBytes" , "(Ljava/nio/charset/Charset;)[B" , false );
245+ }
246+
249247 @ Override
250248 public void visitMaxs (int maxStack , int maxLocals ) {
251249 // ensure we have enough stack allocated for our code
0 commit comments