8261154: Memory leak in Java_java_lang_ClassLoader_defineClass0 with long class names
Reviewed-by: stuefe, chegar, mchung
This commit is contained in:
parent
78b0d32742
commit
07918995da
@ -262,6 +262,9 @@ Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,
|
||||
|
||||
result = JVM_LookupDefineClass(env, lookup, utfName, body, length, pd, initialize, flags, classData);
|
||||
|
||||
if (utfName && utfName != buf)
|
||||
free(utfName);
|
||||
|
||||
free_body:
|
||||
free(body);
|
||||
return result;
|
||||
|
@ -37,6 +37,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
|
||||
|
||||
public class LookupDefineClass {
|
||||
/**
|
||||
* foo.Foo
|
||||
*/
|
||||
private static final byte[] X_BYTECODE = new byte[]{
|
||||
(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE, 0x00, 0x00, 0x00, 0x38, 0x00, 0x10, 0x0A, 0x00,
|
||||
0x03, 0x00, 0x0C, 0x07, 0x00, 0x0D, 0x07, 0x00, 0x0E, 0x07, 0x00, 0x0F,
|
||||
@ -62,6 +65,61 @@ public class LookupDefineClass {
|
||||
0x02, 0x00, 0x0B
|
||||
};
|
||||
|
||||
/**
|
||||
* A variant of X_BYTECODE, with the class name rewritten to trigger malloc in ClassLoader.c
|
||||
*
|
||||
* ClassReader reader = new ClassReader(X_BYTECODE);
|
||||
* ClassWriter writer = new ClassWriter(reader, 0);
|
||||
* reader.accept(new ClassVisitor(Opcodes.ASM5, writer) {
|
||||
* @Override
|
||||
* public void visit(int version, int access, String name,
|
||||
* String signature, String superName, String[] interfaces) {
|
||||
* super.visit(version, access,
|
||||
* "foo/AReallyReallyLongClassNameThatWillSurelyNotFitInACharBufferOfLength128ToTestThatWeDontLeakMemoryWhenTheClassNameIsTooLongForTheStackAllocatedBuffer",
|
||||
* signature, superName, interfaces);
|
||||
* }
|
||||
* }, 0);
|
||||
* byte[] code = writer.toByteArray();
|
||||
* System.out.println(HexFormat.ofDelimiter(", ").withPrefix("0x").formatHex(code));
|
||||
*/
|
||||
private static final byte[] X_LONG_NAME_BYTECODE = new byte[]{
|
||||
(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x38, 0x00, 0x12, 0x0a, 0x00,
|
||||
0x03, 0x00, 0x0c, 0x07, 0x00, 0x0d, 0x07, 0x00, 0x0e, 0x07, 0x00, 0x0f,
|
||||
0x01, 0x00, 0x06, 0x3c, 0x69, 0x6e, 0x69, 0x74, 0x3e, 0x01, 0x00, 0x03,
|
||||
0x28, 0x29, 0x56, 0x01, 0x00, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x01, 0x00,
|
||||
0x0f, 0x4c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x54,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x01, 0x00, 0x03, 0x72, 0x75, 0x6e, 0x01, 0x00,
|
||||
0x0a, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x01,
|
||||
0x00, 0x08, 0x46, 0x6f, 0x6f, 0x2e, 0x6a, 0x61, 0x76, 0x61, 0x0c, 0x00,
|
||||
0x05, 0x00, 0x06, 0x01, 0x00, 0x07, 0x66, 0x6f, 0x6f, 0x2f, 0x46, 0x6f,
|
||||
0x6f, 0x01, 0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e,
|
||||
0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x01, 0x00, 0x12, 0x6a,
|
||||
0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x52, 0x75, 0x6e,
|
||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x01, 0x00, (byte)0x97, 0x66, 0x6f, 0x6f, 0x2f,
|
||||
0x41, 0x52, 0x65, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x61, 0x6c, 0x6c,
|
||||
0x79, 0x4c, 0x6f, 0x6e, 0x67, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x54, 0x68, 0x61, 0x74, 0x57, 0x69, 0x6c, 0x6c, 0x53, 0x75,
|
||||
0x72, 0x65, 0x6c, 0x79, 0x4e, 0x6f, 0x74, 0x46, 0x69, 0x74, 0x49, 0x6e,
|
||||
0x41, 0x43, 0x68, 0x61, 0x72, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x4f,
|
||||
0x66, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x31, 0x32, 0x38, 0x54, 0x6f,
|
||||
0x54, 0x65, 0x73, 0x74, 0x54, 0x68, 0x61, 0x74, 0x57, 0x65, 0x44, 0x6f,
|
||||
0x6e, 0x74, 0x4c, 0x65, 0x61, 0x6b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79,
|
||||
0x57, 0x68, 0x65, 0x6e, 0x54, 0x68, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x49, 0x73, 0x54, 0x6f, 0x6f, 0x4c, 0x6f, 0x6e,
|
||||
0x67, 0x46, 0x6f, 0x72, 0x54, 0x68, 0x65, 0x53, 0x74, 0x61, 0x63, 0x6b,
|
||||
0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x42, 0x75, 0x66,
|
||||
0x66, 0x65, 0x72, 0x07, 0x00, 0x10, 0x00, 0x21, 0x00, 0x11, 0x00, 0x03,
|
||||
0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
|
||||
0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x01,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x2a, (byte)0xb7, 0x00, 0x01, (byte)0xb1, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00,
|
||||
0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x09, 0x00, 0x06, 0x00, 0x01, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, (byte)0xb1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06,
|
||||
0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00,
|
||||
0x00, 0x02, 0x00, 0x0b
|
||||
};
|
||||
|
||||
/**
|
||||
* Our own crippled classloader, that can only load a simple class over and over again.
|
||||
*/
|
||||
@ -207,6 +265,15 @@ public class LookupDefineClass {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public Class<?> loadLongName() throws ClassNotFoundException {
|
||||
try {
|
||||
return HOST_LOOKUP.defineHiddenClass(X_LONG_NAME_BYTECODE, false).lookupClass();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws RunnerException {
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(LookupDefineClass.WeakClass.class.getSimpleName())
|
||||
@ -276,6 +343,15 @@ public class LookupDefineClass {
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public Class<?> loadLongName() throws ClassNotFoundException {
|
||||
try {
|
||||
return HOST_LOOKUP.defineHiddenClass(X_LONG_NAME_BYTECODE, false, STRONG).lookupClass();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws RunnerException {
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(LookupDefineClass.HiddenClass.class.getSimpleName())
|
||||
|
Loading…
x
Reference in New Issue
Block a user