@@ -190,12 +190,18 @@ static class SampledThreadInfo {
190190 private Thread .State state ;
191191 private String threadName ;
192192 private long threadId ;
193+ private long threadCpuTime ;
193194
194195 SampledThreadInfo (String tn , long tid , Thread .State ts , StackTraceElement [] st , InstrumentationFilter filter ) {
196+ this (tn , tid ,ts , st , -1 , filter );
197+ }
198+
199+ SampledThreadInfo (String tn , long tid , Thread .State ts , StackTraceElement [] st , long tct , InstrumentationFilter filter ) {
195200 threadName = tn ;
196201 threadId = tid ;
197202 state = ts ;
198203 stackTrace = st ;
204+ threadCpuTime = tct ;
199205 if (state == Thread .State .RUNNABLE && containsKnownBlockingMethod (st )) { // known blocking method -> change state to waiting
200206 state = Thread .State .WAITING ;
201207 }
@@ -339,6 +345,21 @@ final void addStacktrace(SampledThreadInfo[] threads, long dumpTimeStamp) throws
339345 // }
340346 }
341347 }
348+
349+ final public void addStacktrace (Map <String , Object >[] infoMap , long dumpTimeStamp ) throws IllegalStateException {
350+ List <SampledThreadInfo > threads = new ArrayList <>(infoMap .length );
351+
352+ for (Map <String ,Object > threadInfo : infoMap ) {
353+ String name = (String ) threadInfo .get ("name" );
354+ StackTraceElement [] stack = (StackTraceElement []) threadInfo .get ("stack" );
355+ long tid = (Long ) threadInfo .get ("tid" );
356+ long threadCpuTime = (Long ) threadInfo .get ("threadCpuTime" );
357+ SampledThreadInfo i = new SampledThreadInfo (name , tid , State .RUNNABLE , stack , threadCpuTime , filter );
358+
359+ threads .add (i );
360+ }
361+ addStacktrace (threads .toArray (new SampledThreadInfo [0 ]), dumpTimeStamp );
362+ }
342363
343364 final public void addStacktrace (java .lang .management .ThreadInfo [] threads , long dumpTimeStamp ) throws IllegalStateException {
344365 long timediff = processDumpTimeStamp (dumpTimeStamp );
@@ -383,10 +404,15 @@ private void processThreadDump(final long timediff, final long dumpTimeStamp, fi
383404
384405 long threadId = tinfo .getThreadId ();
385406 if (!threadIds .contains (threadId )) {
407+ long threadCpuTime = tinfo .threadCpuTime ;
386408 threadIds .add (threadId );
387409 threadNames .add (tname );
388410 ccgb .newThread ((int ) threadId , tname , "<none>" );
389- threadtimes .put (threadId ,dumpTimeStamp );
411+ if (threadCpuTime != -1 ) {
412+ threadtimes .put (threadId ,threadCpuTime );
413+ } else {
414+ threadtimes .put (threadId ,dumpTimeStamp );
415+ }
390416 }
391417 StackTraceElement [] newElements = tinfo .getStackTrace ();
392418 SampledThreadInfo oldTinfo = lastStackTrace .get ().get (threadId );
@@ -397,14 +423,14 @@ private void processThreadDump(final long timediff, final long dumpTimeStamp, fi
397423 oldElements = oldTinfo .getStackTrace ();
398424 oldState = oldTinfo .getThreadState ();
399425 }
400- processDiffs ((int ) threadId , oldElements , newElements , dumpTimeStamp , timediff , oldState , newState );
426+ processDiffs ((int ) threadId , oldElements , newElements , dumpTimeStamp , tinfo . threadCpuTime , timediff , oldState , newState );
401427 }
402428
403429 for (SampledThreadInfo oldTinfo : lastStackTrace .get ().values ()) {
404430 if (!tinfoMap .containsKey (oldTinfo .getThreadId ())) {
405431 Thread .State oldState = oldTinfo .getThreadState ();
406432 Thread .State newState = Thread .State .TERMINATED ;
407- processDiffs ((int ) oldTinfo .getThreadId (), oldTinfo .getStackTrace (), NO_STACK_TRACE , dumpTimeStamp , timediff , oldState , newState );
433+ processDiffs ((int ) oldTinfo .getThreadId (), oldTinfo .getStackTrace (), NO_STACK_TRACE , dumpTimeStamp , oldTinfo . threadCpuTime , timediff , oldState , newState );
408434 }
409435 }
410436
@@ -428,12 +454,11 @@ private long processDumpTimeStamp(long dumpTimeStamp) {
428454 return timediff ;
429455 }
430456
431- private void processDiffs (int threadId , StackTraceElement [] oldElements , StackTraceElement [] newElements , long timestamp , long timediff , Thread .State oldState , Thread .State newState ) throws IllegalStateException {
457+ private void processDiffs (int threadId , StackTraceElement [] oldElements , StackTraceElement [] newElements , long timestamp , long threadCpuTime , long timediff , Thread .State oldState , Thread .State newState ) throws IllegalStateException {
432458 assert newState != Thread .State .NEW : "Invalid thread state " + newState .name () + " for taking a stack trace" ; // just to be sure
433459 if (oldState == Thread .State .TERMINATED && newState != Thread .State .TERMINATED ) {
434460 throw new IllegalStateException ("Thread has already been set to " + Thread .State .TERMINATED .name () + " - stack trace can not be taken" );
435461 }
436- long threadtime = threadtimes .get (Long .valueOf (threadId ));
437462 // switch (oldState) {
438463 // case NEW: {
439464 // switch (newState) {
@@ -457,9 +482,15 @@ private void processDiffs(int threadId, StackTraceElement[] oldElements, StackTr
457482 // break;
458483 // }
459484 // }
460- if (oldState == Thread .State .RUNNABLE ) {
461- threadtime += timediff ;
462- threadtimes .put (Long .valueOf (threadId ),threadtime );
485+ long threadtime ;
486+ if (threadCpuTime == -1 ) {
487+ threadtime = threadtimes .get (Long .valueOf (threadId ));
488+ if (oldState == Thread .State .RUNNABLE ) {
489+ threadtime += timediff ;
490+ threadtimes .put (Long .valueOf (threadId ),threadtime );
491+ }
492+ } else {
493+ threadtime = threadCpuTime ;
463494 }
464495 // if (newState == Thread.State.RUNNABLE && newElements.length > 0) {
465496 // StackTraceElement top = newElements[0];
0 commit comments