@@ -190,12 +190,18 @@ static class SampledThreadInfo {
190
190
private Thread .State state ;
191
191
private String threadName ;
192
192
private long threadId ;
193
+ private long threadCpuTime ;
193
194
194
195
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 ) {
195
200
threadName = tn ;
196
201
threadId = tid ;
197
202
state = ts ;
198
203
stackTrace = st ;
204
+ threadCpuTime = tct ;
199
205
if (state == Thread .State .RUNNABLE && containsKnownBlockingMethod (st )) { // known blocking method -> change state to waiting
200
206
state = Thread .State .WAITING ;
201
207
}
@@ -339,6 +345,21 @@ final void addStacktrace(SampledThreadInfo[] threads, long dumpTimeStamp) throws
339
345
// }
340
346
}
341
347
}
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
+ }
342
363
343
364
final public void addStacktrace (java .lang .management .ThreadInfo [] threads , long dumpTimeStamp ) throws IllegalStateException {
344
365
long timediff = processDumpTimeStamp (dumpTimeStamp );
@@ -383,10 +404,15 @@ private void processThreadDump(final long timediff, final long dumpTimeStamp, fi
383
404
384
405
long threadId = tinfo .getThreadId ();
385
406
if (!threadIds .contains (threadId )) {
407
+ long threadCpuTime = tinfo .threadCpuTime ;
386
408
threadIds .add (threadId );
387
409
threadNames .add (tname );
388
410
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
+ }
390
416
}
391
417
StackTraceElement [] newElements = tinfo .getStackTrace ();
392
418
SampledThreadInfo oldTinfo = lastStackTrace .get ().get (threadId );
@@ -397,14 +423,14 @@ private void processThreadDump(final long timediff, final long dumpTimeStamp, fi
397
423
oldElements = oldTinfo .getStackTrace ();
398
424
oldState = oldTinfo .getThreadState ();
399
425
}
400
- processDiffs ((int ) threadId , oldElements , newElements , dumpTimeStamp , timediff , oldState , newState );
426
+ processDiffs ((int ) threadId , oldElements , newElements , dumpTimeStamp , tinfo . threadCpuTime , timediff , oldState , newState );
401
427
}
402
428
403
429
for (SampledThreadInfo oldTinfo : lastStackTrace .get ().values ()) {
404
430
if (!tinfoMap .containsKey (oldTinfo .getThreadId ())) {
405
431
Thread .State oldState = oldTinfo .getThreadState ();
406
432
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 );
408
434
}
409
435
}
410
436
@@ -428,12 +454,11 @@ private long processDumpTimeStamp(long dumpTimeStamp) {
428
454
return timediff ;
429
455
}
430
456
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 {
432
458
assert newState != Thread .State .NEW : "Invalid thread state " + newState .name () + " for taking a stack trace" ; // just to be sure
433
459
if (oldState == Thread .State .TERMINATED && newState != Thread .State .TERMINATED ) {
434
460
throw new IllegalStateException ("Thread has already been set to " + Thread .State .TERMINATED .name () + " - stack trace can not be taken" );
435
461
}
436
- long threadtime = threadtimes .get (Long .valueOf (threadId ));
437
462
// switch (oldState) {
438
463
// case NEW: {
439
464
// switch (newState) {
@@ -457,9 +482,15 @@ private void processDiffs(int threadId, StackTraceElement[] oldElements, StackTr
457
482
// break;
458
483
// }
459
484
// }
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 ;
463
494
}
464
495
// if (newState == Thread.State.RUNNABLE && newElements.length > 0) {
465
496
// StackTraceElement top = newElements[0];
0 commit comments