JDK-8074368 : ThreadMXBean.getThreadInfo() corrupts memory when called with empty array for thread ids
  • Type: Bug
  • Component: core-svc
  • Sub-Component: java.lang.management
  • Affected Version: 8u25
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2015-03-04
  • Updated: 2017-08-31
  • Resolved: 2015-04-08
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.
7u101Fixed 8u72Fixed 9 b64Fixed
Related Reports
Duplicate :  
See description in Java incident

During looking at this issue, I found there are 2 problems. 1. Crash with zero length array of thread Ids. 2. Different behavior among TheadMXBean.getThreadInfo() methods. 1) TheadMXBean.getThreadInfo(new long[] {}, 1): crashes 2) TheadMXBean.getThreadInfo(new long[] {}, true, true): returns all thread informations 3) TheadMXBean.getThreadInfo(new long[] {}, 0):OK, returns 0 4) TheadMXBean.getThreadInfo(new long[] {}):OK, returns 0 --------------------------- The root cause is "static void do_thread_dump(, , num_threads, , , , ) at management.cpp" is not working as expected. Inside of this function, VM_ThreadDump is used and when we pass 0 for num_threads parameter, VM_ThreadDump will work as to dump all threads. But do_thread_dump() is designed to get nothing when num_threads=0 comes. So simply adding a test of "if (num_threads > 0)" before calling VM_ThreadDump op will change to work as expected. And also fixes above 2 issues.

I could reproduce with Jon's suggestion. The reason is when gets zero length array of ids in jmm_GetThreadInfo(), it tries to put an object at an address which is out of array.

ILW = High (crash), Medium (easily reproducible but not a common case in real code), Low (don't pass zero length array to TheadMXBean.getThreadInfo()) = P2

Crash in code is here src/share/vm/oops/oop.inline.hpp:461 459 } else { 460 // Must be zero, so bite the bullet and take the virtual call. 461 s = klass->oop_size(this); 462 } See Java incident for explanation of zero length array. Reproduced it with the submitted reproducer. In a debug build will have to comment out some assertions to get to the JVM crash in a debug build. diff --git a/src/share/vm/oops/objArrayOop.hpp b/src/share/vm/oops/objArrayOop.hpp --- a/src/share/vm/oops/objArrayOop.hpp +++ b/src/share/vm/oops/objArrayOop.hpp @@ -38,7 +38,7 @@ friend class G1ParScanPartialArrayClosure; template <class T> T* obj_at_addr(int index) const { - assert(is_within_bounds(index), "index out of bounds"); + // assert(is_within_bounds(index), "index out of bounds"); return &((T*)base())[index]; } diff --git a/src/share/vm/services/management.cpp b/src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp +++ b/src/share/vm/services/management.cpp @@ -1218,7 +1218,7 @@ } int num_snapshots = dump_result.num_snapshots(); - assert(num_snapshots == num_threads, "Must match the number of thread snapshots"); + // assert(num_snapshots == num_threads, "Must match the number of thread snapshots"); int index = 0; for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; index++, ts = ts->next()) { // For each thread, create an java/lang/management/ThreadInfo object