JDK-7195620 : NPG: Test VMMismatchException001 gets an java.lang.ArrayIndexOutOfBoundsException
  • Type: Bug
  • Component: core-svc
  • Sub-Component: debugger
  • Affected Version: 8
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2012-08-31
  • Updated: 2012-09-12
  • Resolved: 2012-09-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8Resolved
Related Reports
Duplicate :  
Description
The NSK test

nsk/jdi/VMMismatchException/VMMismatchException001

fails because something isn't returned by the VM that it expects:

# ERROR: Unexpected exception: java.lang.ArrayIndexOutOfBoundsException: 0
java.lang.ArrayIndexOutOfBoundsException: 0
        at java.util.Arrays$ArrayList.get(Arrays.java:2875)
        at nsk.jdi.VMMismatchException.VMMismatchException001.VMMismatchException
001.doThreadReferenceStop(VMMismatchException001.java:398)
        at nsk.jdi.VMMismatchException.VMMismatchException001.VMMismatchException
001.checkThreadReferenceStop(VMMismatchException001.java:391)
        at nsk.jdi.VMMismatchException.VMMismatchException001.VMMismatchException
001.main(VMMismatchException001.java:812)
The failing test holds a reference to a thread with only static java method frames. The test has an instance of java.lang.Exception in a static field of one of the classes in the frames of the thread. However, the class is never found by the FollowReferences call.

Before the perm gen removal, this class was found when the context class loader of the thread was traversed. The class would be found in the ClassLoader.classes Vector. This vector is not populated anymore, so the class is not found.

Comments
EVALUATION The spec for JVM/TI FollowReferences is here: http://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#FollowReferences There are several key pieces to the description: > This function initiates a traversal over the objects that are > directly and indirectly reachable from the specified object or, > if initial_object is not specified, all objects reachable from > the heap roots. The heap root are the set of system classes, > JNI globals, references from thread stacks, and other objects > used as roots for the purposes of garbage collection. The above tells me that FollowReferences should do the same traversal over the objects that a garbage collection pass would do. And the following: > This function operates by traversing the reference graph. Before the Perm Gen Removal project, ClassLoader.classes provided a Java level reference from the class loader to the classes defined by the class loader. After the PGR project, the linkage from class loader to classes defined by the class loader is implemented by C++ code and data structures rather than a Java level reference. However, the garbage collector still traverses from the class loader to the classes defined by the class loader. It seems to me that JVM/TI FollowReferences needs to be updated to traverse from the class loader via the new C++ infrastructure to the classes defined by the class loader. One other point from the spec: > This function reports a Java programming language view of object > references, not a virtual machine implementation view. Since the new linkage from class loader to classes defined by the class loader is now implemented by C++ code and data structures, it seems to me that FollowReferences() should not try and report the internal C++ data structure. I'm specifically saying here that we don't need to add a new jvmtiHeapReferenceKind. In the pre-PGR code base, I think the classes defined by a class loader are reported as JVMTI_HEAP_REFERENCE_FIELD and I would do the same in the PGR code base to preserve compatibility.
12-09-2012

EVALUATION The spec for ReferenceType.instances() is here: http://docs.oracle.com/javase/7/docs/jdk/api/jpda/jdi/com/sun/jdi/ReferenceType.html#instances(long) The key part of the description says: > Returns instances of this ReferenceType. Only instances that > are reachable for the purposes of garbage collection are returned. Since the debugee VM is still running the test class (VMMismatchException001a), the test class is still reachable for purposes of garbage collection. This means that ReferenceType.instances() should return the java.lang.Exception instance that is assigned to VMMismatchException001a.exceptionInstance.
12-09-2012

EVALUATION The test is failing in this block of code: nsk/jdi/VMMismatchException/VMMismatchException001/VMMismatchException001.java: 395 try { 396 ThreadReference thread = debuggee1.threadByName(VMMismatchException001a.mainThreadName); 397 398 thread.stop(debuggee2.classByName("java.lang.Exception").instances(1).get(0)); 399 400 success = false; 401 log.complain("Expected 'VMMismatchException' was not thrown" ); 402 } catch (VMMismatchException e) { 403 log.display("Got expected exception: " + e); 404 } catch (Throwable t) { 405 success = false; 406 log.complain("Unexpected exception: " + t); 407 t.printStackTrace(log.getOutStream()); 408 } Specifically on line 398: thread.stop(debuggee2.classByName("java.lang.Exception").instances(1).get(0)); we get the following exception: java.lang.ArrayIndexOutOfBoundsException: 0 at java.util.Arrays$ArrayList.get(Arrays.java:2875) at nsk.jdi.VMMismatchException.VMMismatchException001.VMMismatchException001.doThreadReferenceStop(VMMismatchException001.java:398) Let's decompose the parameter to thread.stop(): debuggee2 // var of type Debugee extends DebugeeProcess // part of JDI test infrastructure .classByName("java.lang.Exception") // returns the ReferenceType for the name class // i.e., the mirror for the class in the debugee VM .instances(1) // return a List<ObjectReference> of java.lang.Exception // parameter of '1' means only return an array of at most one (1) .get(0) // get the one element from the array returned by instances() // assumes that instances always returns at least one element So the test program has successfully gotten a ReferenceType that refers to the java.lang.Exception mirror from the debugee VM. The test program then asks for at most one instance of a java.lang.Exception object which returns an empty array. The test always expects to be able to get at least one instance so there is no sanity check of the instances(1) call return value. I think this is a reasonable assumption for the test to make. As Stefan points out in the comment notes, the implementation of ReferenceType.instances() assumes that JVM/TI FollowReferences() will be able to find the instance of java.lang.Exception that is squirreled away in the class being run by the debugee VM (in the static field VMMismatchException001a.exceptionInstance). The ReferenceType.instances() call used to work when the ClassLoader.classes Vector was populated because FollowReferences() was able to get from the Thread -> contextClassLoader -> VMMismatchException001a -> exceptionInstance field. Stefan includes the exact traversal in the comment notes. I'm having trouble shaking this feeling that this test's use of ReferenceType.instances() has been working "by accident". This will require more mulling.
11-09-2012