vendredi 31 mai 2019

Java ThreadLocal dump values from all threads

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();
            }
        }
    }

}





Aucun commentaire:

Enregistrer un commentaire