Skip to content

Commit 0791899

Browse files
committed
8261154: Memory leak in Java_java_lang_ClassLoader_defineClass0 with long class names
Reviewed-by: stuefe, chegar, mchung
1 parent 78b0d32 commit 0791899

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

src/java.base/share/native/libjava/ClassLoader.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,
262262

263263
result = JVM_LookupDefineClass(env, lookup, utfName, body, length, pd, initialize, flags, classData);
264264

265+
if (utfName && utfName != buf)
266+
free(utfName);
267+
265268
free_body:
266269
free(body);
267270
return result;

test/micro/org/openjdk/bench/java/lang/invoke/LookupDefineClass.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
3838

3939
public class LookupDefineClass {
40+
/**
41+
* foo.Foo
42+
*/
4043
private static final byte[] X_BYTECODE = new byte[]{
4144
(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE, 0x00, 0x00, 0x00, 0x38, 0x00, 0x10, 0x0A, 0x00,
4245
0x03, 0x00, 0x0C, 0x07, 0x00, 0x0D, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0F,
@@ -62,6 +65,61 @@ public class LookupDefineClass {
6265
0x02, 0x00, 0x0B
6366
};
6467

68+
/**
69+
* A variant of X_BYTECODE, with the class name rewritten to trigger malloc in ClassLoader.c
70+
*
71+
* ClassReader reader = new ClassReader(X_BYTECODE);
72+
* ClassWriter writer = new ClassWriter(reader, 0);
73+
* reader.accept(new ClassVisitor(Opcodes.ASM5, writer) {
74+
* @Override
75+
* public void visit(int version, int access, String name,
76+
* String signature, String superName, String[] interfaces) {
77+
* super.visit(version, access,
78+
* "foo/AReallyReallyLongClassNameThatWillSurelyNotFitInACharBufferOfLength128ToTestThatWeDontLeakMemoryWhenTheClassNameIsTooLongForTheStackAllocatedBuffer",
79+
* signature, superName, interfaces);
80+
* }
81+
* }, 0);
82+
* byte[] code = writer.toByteArray();
83+
* System.out.println(HexFormat.ofDelimiter(", ").withPrefix("0x").formatHex(code));
84+
*/
85+
private static final byte[] X_LONG_NAME_BYTECODE = new byte[]{
86+
(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x38, 0x00, 0x12, 0x0a, 0x00,
87+
0x03, 0x00, 0x0c, 0x07, 0x00, 0x0d, 0x07, 0x00, 0x0e, 0x07, 0x00, 0x0f,
88+
0x01, 0x00, 0x06, 0x3c, 0x69, 0x6e, 0x69, 0x74, 0x3e, 0x01, 0x00, 0x03,
89+
0x28, 0x29, 0x56, 0x01, 0x00, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x01, 0x00,
90+
0x0f, 0x4c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x54,
91+
0x61, 0x62, 0x6c, 0x65, 0x01, 0x00, 0x03, 0x72, 0x75, 0x6e, 0x01, 0x00,
92+
0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x01,
93+
0x00, 0x08, 0x46, 0x6f, 0x6f, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x0c, 0x00,
94+
0x05, 0x00, 0x06, 0x01, 0x00, 0x07, 0x66, 0x6f, 0x6f, 0x2f, 0x46, 0x6f,
95+
0x6f, 0x01, 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e,
96+
0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x01, 0x00, 0x12, 0x6a,
97+
0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x52, 0x75, 0x6e,
98+
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x01, 0x00, (byte)0x97, 0x66, 0x6f, 0x6f, 0x2f,
99+
0x41, 0x52, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x61, 0x6c, 0x6c,
100+
0x79, 0x4c, 0x6f, 0x6e, 0x67, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61,
101+
0x6d, 0x65, 0x54, 0x68, 0x61, 0x74, 0x57, 0x69, 0x6c, 0x6c, 0x53, 0x75,
102+
0x72, 0x65, 0x6c, 0x79, 0x4e, 0x6f, 0x74, 0x46, 0x69, 0x74, 0x49, 0x6e,
103+
0x41, 0x43, 0x68, 0x61, 0x72, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4f,
104+
0x66, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x31, 0x32, 0x38, 0x54, 0x6f,
105+
0x54, 0x65, 0x73, 0x74, 0x54, 0x68, 0x61, 0x74, 0x57, 0x65, 0x44, 0x6f,
106+
0x6e, 0x74, 0x4c, 0x65, 0x61, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
107+
0x57, 0x68, 0x65, 0x6e, 0x54, 0x68, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73,
108+
0x4e, 0x61, 0x6d, 0x65, 0x49, 0x73, 0x54, 0x6f, 0x6f, 0x4c, 0x6f, 0x6e,
109+
0x67, 0x46, 0x6f, 0x72, 0x54, 0x68, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b,
110+
0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x75, 0x66,
111+
0x66, 0x65, 0x72, 0x07, 0x00, 0x10, 0x00, 0x21, 0x00, 0x11, 0x00, 0x03,
112+
0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
113+
0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x01,
114+
0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x2a, (byte)0xb7, 0x00, 0x01, (byte)0xb1, 0x00,
115+
0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00,
116+
0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x09, 0x00, 0x06, 0x00, 0x01, 0x00,
117+
0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
118+
0x01, (byte)0xb1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06,
119+
0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00,
120+
0x00, 0x02, 0x00, 0x0b
121+
};
122+
65123
/**
66124
* Our own crippled classloader, that can only load a simple class over and over again.
67125
*/
@@ -207,6 +265,15 @@ public Class<?> load() throws ClassNotFoundException {
207265
}
208266
}
209267

268+
@Benchmark
269+
public Class<?> loadLongName() throws ClassNotFoundException {
270+
try {
271+
return HOST_LOOKUP.defineHiddenClass(X_LONG_NAME_BYTECODE, false).lookupClass();
272+
} catch (IllegalAccessException e) {
273+
throw new InternalError(e);
274+
}
275+
}
276+
210277
public static void main(String[] args) throws RunnerException {
211278
Options opt = new OptionsBuilder()
212279
.include(LookupDefineClass.WeakClass.class.getSimpleName())
@@ -276,6 +343,15 @@ public Class<?> load() throws ClassNotFoundException {
276343
}
277344
}
278345

346+
@Benchmark
347+
public Class<?> loadLongName() throws ClassNotFoundException {
348+
try {
349+
return HOST_LOOKUP.defineHiddenClass(X_LONG_NAME_BYTECODE, false, STRONG).lookupClass();
350+
} catch (IllegalAccessException e) {
351+
throw new InternalError(e);
352+
}
353+
}
354+
279355
public static void main(String[] args) throws RunnerException {
280356
Options opt = new OptionsBuilder()
281357
.include(LookupDefineClass.HiddenClass.class.getSimpleName())

0 commit comments

Comments
 (0)