package net.djpowell.liverepl.discovery.impl; import net.djpowell.liverepl.discovery.ClassLoaderDiscovery; import net.djpowell.liverepl.discovery.ClassLoaderInfo; import net.djpowell.liverepl.discovery.ClassLoaderRegistry; import java.util.*; /** * Implementation of ClassLoaderDiscovery that makes available the Thread Context ClassLoaders * associated with currently running threads. */ public class ThreadDiscovery implements ClassLoaderDiscovery { private final ClassLoaderRegistry registry; public ThreadDiscovery(ClassLoaderRegistry registry) { this.registry = registry; } public Collection<ClassLoaderInfo> listClassLoaders() { Collection<ClassLoaderInfo> ret = new ArrayList<ClassLoaderInfo>(); ClassLoader systemCl = ClassLoader.getSystemClassLoader(); Collection<Thread> threads = new HashSet<Thread>(Thread.getAllStackTraces().keySet()); Map<ClassLoader, String> classLoaders = new HashMap<ClassLoader, String>(); for (Thread thread : threads) { ClassLoader classLoader = thread.getContextClassLoader(); if (classLoader == null) continue; if (classLoader == systemCl) continue; classLoaders.put(classLoader, thread.getName() + " #" + thread.getId() + " [" + thread.getThreadGroup().getName() + "]"); } TreeSet<Map.Entry<ClassLoader, String>> entries = new TreeSet<Map.Entry<ClassLoader, String>>( new Comparator<Map.Entry<ClassLoader, String>>() { public int compare(Map.Entry<ClassLoader, String> o1, Map.Entry<ClassLoader, String> o2) { return o1.getValue().compareTo(o2.getValue()); } }); entries.addAll(classLoaders.entrySet()); for (Map.Entry<ClassLoader, String> entry : entries) { ClassLoader classLoader = entry.getKey(); String threadName = entry.getValue(); String id = registry.registerClassLoader(classLoader); ClassLoaderInfo cli = new ClassLoaderInfo(id, classLoader, threadName); ret.add(cli); } return ret; } public String discoveryName() { return "Thread Context Class Loaders"; } }