import java.lang.ref.Reference; import java.lang.reflect.Field; /** * */ public class ThreadLocalTest { private static ThreadLocal threadLocal; public static void main(String[] args) throws Exception { System.out.println(System.getProperty("java.version")); threadLocal = new ThreadLocal(); threadLocal.set(">>> LEAK <<<"); // threadLocal.remove(); threadLocal = null; Runtime.getRuntime().gc(); printThreadLocals(Thread.currentThread()); } private static void printThreadLocals(Thread thread) throws IllegalAccessException, NoSuchFieldException { Object threadLocals = getFieldValue(thread, "threadLocals"); Object[] table = (Object[]) getFieldValue(threadLocals, "table"); for (Object entry : table) { if (entry != null) { Object threadLocal = getFieldValue(Reference.class, entry, "referent"); Object threadLocalValue = getFieldValue(entry, "value"); System.out.println(threadLocal + " = " + threadLocalValue); } } } private static Object getFieldValue(Object obj, String fieldName) throws IllegalAccessException, NoSuchFieldException { return getFieldValue(obj.getClass(), obj, fieldName); } private static Object getFieldValue(Class clazz, Object obj, String fieldName) throws IllegalAccessException, NoSuchFieldException { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(obj); } }