EVALUATION
http://hg.openjdk.java.net/hsx/hsx19/baseline/rev/04323991c395
|
|
|
EVALUATION
http://hg.openjdk.java.net/jdk7/hotspot-gc/hotspot/rev/2528b5bd749c
|
|
|
EVALUATION
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
--- a/src/share/vm/oops/instanceKlass.cpp
+++ b/src/share/vm/oops/instanceKlass.cpp
@@ -382,7 +382,7 @@ void instanceKlass::initialize_impl(inst
const char* desc = "Could not initialize class ";
const char* className = this_oop->external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
- char* message = NEW_C_HEAP_ARRAY(char, msglen);
+ char* message = NEW_RESOURCE_ARRAY(char, msglen);
if (NULL == message) {
// Out of memory: can't create detailed error message
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
|
|
|
EVALUATION
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/rev/2528b5bd749c
|
|
|
EVALUATION
http://hg.openjdk.java.net/jdk7/hotspot-rt/hotspot/rev/2528b5bd749c
|
|
|
EVALUATION
I tried valgrid to spot the problem and it showed very suspicious alloction site:
malloc
os::malloc(unsigned long)
instanceKlass::initialize_impl(instanceKlassHandle, Thread*)
instanceKlass::initialize(Thread*) (in /opt/sun-jdk-1.6.0.17/jre/lib/amd64/server/libjvm.so)
find_class_from_class_loader(JNIEnv_*, symbolHandle, unsigned char, Handle, Handle, unsigned char, Thread*)
jvm_find_class_from_class_loader(JNIEnv_*, char const*, unsigned char, _jobject*, unsigned char, Thread*)
JVM_FindClassFromClassLoader
Java_java_lang_Class_forName0
349,860 bytes in 9,996 blocks are definitely lost in loss record 1,162 of 1,163
I used the test case listed below. It receives an integer as an input - a number of loading attempts. Reported amount of leaked memory in aforementioned allocation site depends on the number of attempts.
Test.java:
class Invalid {
static {
if (5>0) throw new RuntimeException(); // to deceive javac
}
}
public class Test {
public static void main (String[] args) throws Exception {
int count = Integer.parseInt(args[0]);
for (int i=0; i < count; i++) {
try {
Class.forName("Invalid");
} catch (Throwable t) {}
}
}
}
|
|
|
EVALUATION
We're leaking the message string from here:
// Step 5
if (this_oop->is_in_error_state()) {
DTRACE_CLASSINIT_PROBE_WAIT(erroneous, instanceKlass::cast(this_oop()), -1,wait);
ResourceMark rm(THREAD);
const char* desc = "Could not initialize class ";
const char* className = this_oop->external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
char* message = NEW_C_HEAP_ARRAY(char, msglen);
if (NULL == message) {
// Out of memory: can't create detailed error message
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
} else {
jio_snprintf(message, msglen, "%s%s", desc, className);
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
}
}
The char* contents will get copied into a Java String's internal char[] when creating the Exception object, and we never free the original array.
|
|
|
|