diff --git a/class-inject/src/glue/java/datadog/instrument/glue/DefineClassGlueGenerator.java b/class-inject/src/glue/java/datadog/instrument/glue/DefineClassGlueGenerator.java index 06c523b..224ecac 100644 --- a/class-inject/src/glue/java/datadog/instrument/glue/DefineClassGlueGenerator.java +++ b/class-inject/src/glue/java/datadog/instrument/glue/DefineClassGlueGenerator.java @@ -25,8 +25,8 @@ /** * Generates glue bytecode for a {@link BiFunction} around {@code ClassLoader.defineClass} that * accepts a map of class-names to bytecode and a class-loader (or protection domain) and returns - * the defined classes. The glue bytecode is encoded as a UTF-16BE string and written as a constant - * inside a Java class at build-time. + * the defined classes. The glue bytecode is encoded as an ISO-8859-1 string and written as a + * constant inside a Java class at build-time. * *
At runtime the glue bytecode is decoded from the string and defined as a hidden/anonymous
* class using instrumentation. This class provides access to {@code ClassLoader.defineClass}
@@ -414,11 +414,6 @@ static byte[] generateBytecode(String unsafeNamespace) {
mv.visitMaxs(-1, -1);
mv.visitEnd();
- // pad bytecode to even number of bytes, to make string encoding/decoding easier
- if ((unsafeNamespace.length() & 0x01) == 0) {
- cw.newConst(0);
- }
-
cw.visitEnd();
return cw.toByteArray();
diff --git a/class-inject/src/main/java/datadog/instrument/classinject/ClassInjector.java b/class-inject/src/main/java/datadog/instrument/classinject/ClassInjector.java
index c51390f..3c29462 100644
--- a/class-inject/src/main/java/datadog/instrument/classinject/ClassInjector.java
+++ b/class-inject/src/main/java/datadog/instrument/classinject/ClassInjector.java
@@ -290,9 +290,12 @@ public void visitCode() {
mv.visitLdcInsn(DefineClassGlue.V8);
}
- // unpack the UTF-16BE encoded string back into bytecode
+ // unpack the ISO-8859-1 encoded glue string back into bytecode
mv.visitFieldInsn(
- GETSTATIC, "java/nio/charset/StandardCharsets", "UTF_16BE", "Ljava/nio/charset/Charset;");
+ GETSTATIC,
+ "java/nio/charset/StandardCharsets",
+ "ISO_8859_1",
+ "Ljava/nio/charset/Charset;");
mv.visitMethodInsn(
INVOKEVIRTUAL, "java/lang/String", "getBytes", "(Ljava/nio/charset/Charset;)[B", false);
diff --git a/class-inject/src/test/java/datadog/instrument/glue/DefineClassGlueGeneratorTest.java b/class-inject/src/test/java/datadog/instrument/glue/DefineClassGlueGeneratorTest.java
index a68e0cc..d234c3f 100644
--- a/class-inject/src/test/java/datadog/instrument/glue/DefineClassGlueGeneratorTest.java
+++ b/class-inject/src/test/java/datadog/instrument/glue/DefineClassGlueGeneratorTest.java
@@ -1,5 +1,6 @@
package datadog.instrument.glue;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.PrintWriter;
@@ -22,4 +23,18 @@ void generatedBytecodePassesVerification(String unsafeNamespace) {
assertThat(errors.toString()).isEmpty();
}
+
+ /** ClassInjector inlines the glue unpacking, so check the packed glue decodes as expected. */
+ @ParameterizedTest
+ @ValueSource(strings = {"sun/misc", "jdk/internal/misc"})
+ void packedGlueUnpacksToGeneratedBytecode(String unsafeNamespace) {
+ byte[] originalBytecode = DefineClassGlueGenerator.generateBytecode(unsafeNamespace);
+ String packedBytecode =
+ "sun/misc".equals(unsafeNamespace) ? DefineClassGlue.V8 : DefineClassGlue.V9;
+
+ // mirrors exactly what ClassInjector's generated bytecode does at runtime
+ byte[] decodedBytecode = packedBytecode.getBytes(ISO_8859_1);
+
+ assertThat(decodedBytecode).isEqualTo(originalBytecode);
+ }
}
diff --git a/utils/src/main/java/datadog/instrument/glue/Glue.java b/utils/src/main/java/datadog/instrument/glue/Glue.java
index 65c3824..afd1270 100644
--- a/utils/src/main/java/datadog/instrument/glue/Glue.java
+++ b/utils/src/main/java/datadog/instrument/glue/Glue.java
@@ -6,7 +6,7 @@
package datadog.instrument.glue;
-import static java.nio.charset.StandardCharsets.UTF_16BE;
+import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.util.Objects.requireNonNull;
import datadog.instrument.utils.JVM;
@@ -26,7 +26,7 @@ private Glue() {}
* @return the unpacked bytecode
*/
public static byte[] unpackBytecode(String bytecode) {
- return bytecode.getBytes(UTF_16BE);
+ return bytecode.getBytes(ISO_8859_1);
}
/**
diff --git a/utils/src/main/java/datadog/instrument/glue/GlueGenerator.java b/utils/src/main/java/datadog/instrument/glue/GlueGenerator.java
index 55a47ac..d8637a4 100644
--- a/utils/src/main/java/datadog/instrument/glue/GlueGenerator.java
+++ b/utils/src/main/java/datadog/instrument/glue/GlueGenerator.java
@@ -51,31 +51,20 @@ public static void classHeader(List The bytecode must be padded to have even length, as this simplifies the encoding/decoding.
- *
* @param lines the list collecting the source code
* @param bytecode the bytecode to pack
*/
public static void packBytecode(List