FULL PRODUCT VERSION : A DESCRIPTION OF THE PROBLEM : If there is an array of size close to 2 GB, its size is reported as a negative value to the heap_iteration_callback in IterateThroughHeap THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Did not try STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Compile a Java class NegativeArraySize (see source code) which creates a big char[] and calls a native method to trigger IterateThroughHeap 2. Compile a C++ agent as a 64-bit dll to get agent.dll 3. Run the test: <path to 64-bit Java 7 or Java 6>/java -Xmx4G -agentlib:agent -cp . NegativeArraySize An object with negative size will be reported. EXPECTED VERSUS ACTUAL BEHAVIOR : Actual: "negative size: array_length=1074790398" Expected: a negative size is never reported REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- =========================================== The Java class: =========================================== public class NegativeArraySize { static native void iterateHeap(); static char[] array = new char[1074790398]; // keep from GC public static void main(String[] args) { iterateHeap(); } } =========================================== The C++ agent: =========================================== #include <stdio.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <jvmti.h> static jvmtiEnv* ourJVMTI; #define ZERO(X) memset(&X, 0, sizeof(X)) /* Check for JVMTI error */ void check_JVMTI_error_impl(jvmtiError err, const char* file, int line) { if (err != JVMTI_ERROR_NONE) { char* name = NULL; ourJVMTI->GetErrorName(err, &name); fprintf(stderr, "ERROR: JVMTI error err=%d(%s) in %s:%d\n", err, name, file, line); fflush(stderr); ourJVMTI->Deallocate((unsigned char *)name); assert(false); } } #define CALL_JVMTI(call_expr) check_JVMTI_error_impl(ourJVMTI->call_expr, __FILE__, __LINE__) jint JNICALL my_callback(jlong class_tag, jlong size, jlong* tag_ptr, jint array_length, void*) { if (size < 0) { printf("negative size: array_length=%d\n", array_length); } return JVMTI_VISIT_OBJECTS; } extern "C" JNIEXPORT void JNICALL Java_NegativeArraySize_iterateHeap(JNIEnv* jni, jclass) { jvmtiHeapCallbacks callbacks; ZERO(callbacks); callbacks.heap_iteration_callback = &my_callback; CALL_JVMTI( IterateThroughHeap(JVMTI_HEAP_FILTER_TAGGED, NULL, &callbacks, NULL) ); } extern "C" JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* /*reserved*/) { vm->GetEnv((void **)&ourJVMTI, JVMTI_VERSION); assert(ourJVMTI); jvmtiCapabilities capabilities; ZERO(capabilities); capabilities.can_tag_objects = 1; CALL_JVMTI(AddCapabilities(&capabilities)); return 0; } ---------- END SOURCE ----------
|