I have ThreadLocal
that store instances of MyClass. I wish to dump (print, sysout) values (instances) of MyClass from all threads.
I have two implementations, but all of them print value only from the current thread (Thread.currentThread()
). Any ideas what I've missed?
P.S. Unfortunately, ThreadLocal API is private so I have to use reflection to get access to ThreadLocalMap
that actually keeps values (e.g. see Thread.threadLocals
etc.)
public class ThreadLocalT{
private Method getMap;
private Field tableField;
private Field value;
private Method getEntry;
public ThreadLocalT() {
try {
getMap = ThreadLocal.class.getDeclaredMethod("getMap", Thread.class);
getMap.setAccessible(true);
Class<?> threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
getEntry = threadLocalMapClass.getDeclaredMethod("getEntry", ThreadLocal.class);
getEntry.setAccessible(true);
tableField = threadLocalMapClass.getDeclaredField("table");
tableField.setAccessible(true);
Class<?> entryClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap$Entry");
value = entryClass.getDeclaredField("value");
value.setAccessible(true);
} catch (NoSuchMethodException | SecurityException | ClassNotFoundException | NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void dump(ThreadLocal<MyClass> pThreadLocal) {
// Implementation I
for (Thread item : Thread.getAllStackTraces().keySet()) {
try {
Object data = getMap.invoke(pThreadLocal, item);
if (data != null) {
Object entry = getEntry.invoke(data, pThreadLocal);
if (entry != null) {
Object obj = value.get(entry);
if (obj != null) {
System.out.println(item);
System.out.println("data = " + data);
System.out.println("entry = " + entry);
System.out.println("obj = " + obj);
}
}
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Implementation II
for (Thread item : Thread.getAllStackTraces().keySet()) {
try {
Object result = getMap.invoke(pThreadLocal, item);
if (result != null) {
Object table = tableField.get(result);
if (table != null) {
int threadLocalCount = Array.getLength(table);
for (int i=0; i < threadLocalCount; i++) {
Object entry = Array.get(table, i);
if (entry != null) {
Object obj = value.get(entry);
if (obj instanceof MyClass) {
System.out.println("obj = " + obj);
}
}
}
}
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}