#2 (CPU time information in thread dumps) seems to have failed to multiply by 100, needed for percentages to ever be anything but 0%.
#2 (CPU) and #3 (deadlocks) did not consider the fact that JMX calls can throw UOE.
In certain cases (observed “in the wild”) this led to some slaves having an empty thread dump;
errors.txt listed the problem:
Could not attach 'nodes/slave/…/thread-dump.txt' to support bundle
-----------------------------------------------------------------------
java.lang.NullPointerException
	at java.lang.management.ThreadInfo.<init>(Unknown Source)
	at sun.management.ThreadImpl.dumpThreads0(Native Method)
	at sun.management.ThreadImpl.dumpAllThreads(Unknown Source)
	at com.cloudbees.jenkins.support.impl.ThreadDumps.threadDumpModern(ThreadDumps.java:157)
	at com.cloudbees.jenkins.support.impl.ThreadDumps.threadDump(ThreadDumps.java:138)
	at com.cloudbees.jenkins.support.impl.ThreadDumps$GetThreadDump.call(ThreadDumps.java:121)
	at com.cloudbees.jenkins.support.impl.ThreadDumps$GetThreadDump.call(ThreadDumps.java:113)
	at hudson.remoting.UserRequest.perform(UserRequest.java:118)
	at hudson.remoting.UserRequest.perform(UserRequest.java:48)
	at hudson.remoting.Request$2.run(Request.java:326)
	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
	at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)