1、Thread类实现了Runnable的接口
public class Thread implements RunnableRunnable的源码只有一个抽象的run方法,并被注解@FunctionalInterface 定义了函数式接口,它们主要用在Lambda表达式和方法引用,使用Lambda时必须是函数式接口,这就是使用lambda表达式创建线程的方式,简化了代码
new Thread(() -> System.out.println("lambda表达式")).start();2、初始化
/* Make sure registerNatives is the first thing <clinit> does. 确保registerNatives是所做的第一件事。*/ private static native void registerNatives(); static { registerNatives(); }从上面的代码中看到定义了一个静态初始化块,我们知道当创建Java对象时,系统总是先调用静态初始化块 在上面的静态初始化块中调用了registerNatives()方法,并且使用了private来修饰,表面这个方法是私有的并不被外部调用。 在Java中使用native关键字修饰的方法,说明此方法并不是由Java中完成的,而是通过C/C++来完成的,并被编译成.dll,之后才由Java调用。方法的具体实现是在dll文件中,当然对于不同平台实现的细节也有所不同,以上registerNatives()方法主要作用就是将C/C++中的方法映射到Java中的native方法,实现方法命名的解耦
这篇解释的原文链接:https://blog.csdn.net/liudaohonglk/article/details/78278368
3、属性
private volatile String name; // 线程名字 private int priority; // 优先级 private Thread threadQ; private long eetop; /* Whether or not to single_step this thread. */ //是否是单步执行 private boolean single_step; /* Whether or not the thread is a daemon thread. */ //是否是守护线程 private boolean daemon = false; /* JVM state */ // 虚拟机状态 private boolean stillborn = false; /* What will be run. */ //将会被执行的Runnable.使用Runnabke方式创建线程时所用 private Runnable target; /* The group of this thread */ //线程分组 private ThreadGroup group; /* The context ClassLoader for this thread */ //这个线程的上下文 private ClassLoader contextClassLoader; /* The inherited AccessControlContext of this thread */ //继承的请求控制 private AccessControlContext inheritedAccessControlContext; /* For autonumbering anonymous threads. */ //默认线程的自动编号 private static int threadInitNumber; private static synchronized int nextThreadNum() { return threadInitNumber++; } /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ // 用于修饰或说明这个线程ThreadLocal值。这个map是由ThreadLocal类 ThreadLocal.ThreadLocalMap threadLocals = null; /* * InheritableThreadLocal values pertaining to this thread. This map is * maintained by the InheritableThreadLocal class. */ //InheritableThreadLocal值属于该线程。这张地图是由InheritableThreadLocal类维护 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; /* * The requested stack size for this thread, or 0 if the creator did * not specify a stack size. It is up to the VM to do whatever it * likes with this number; some VMs will ignore it. */ //该线程请求的堆栈大小 默认一般都是忽略 private long stackSize; /* * JVM-private state that persists after native thread termination. */ //JVM-private原生线程终止后持续状态 private long nativeParkEventPointer; /* * Thread ID */ //每个线程都有专属ID,但名字可能重复 private long tid; /* For generating thread ID */ //用来生成thread ID private static long threadSeqNumber; /* Java thread status for tools, * initialized to indicate thread 'not yet started' */ //标识线程状态,默认是线程未启动 private volatile int threadStatus = 0; //得到下个thread ID private static synchronized long nextThreadID() { return ++threadSeqNumber; } /** * The argument supplied to the current call to * java.util.concurrent.locks.LockSupport.park. * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker * Accessed using java.util.concurrent.locks.LockSupport.getBlocker */ //中断阻塞器:当线程发生IO中断时,需要在线程被设置为中断状态后调用该对象的interrupt方法 volatile Object parkBlocker; /* The object in which this thread is blocked in an interruptible I/O * operation, if any. The blocker's interrupt method should be invoked * after setting this thread's interrupt status. */ //阻塞器锁,主要用于处理阻塞情况 private volatile Interruptible blocker; private final Object blockerLock = new Object(); /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code */ //阻断锁 void blockedOn(Interruptible b) { synchronized (blockerLock) { blocker = b; } } /** * The minimum priority that a thread can have. */ //线程的优先级中最小的 public final static int MIN_PRIORITY = 1; /** * The default priority that is assigned to a thread. */ //线程的优先级中第二的同时也是默认的优先级 public final static int NORM_PRIORITY = 5; /** * The maximum priority that a thread can have. */ //最高的优先级 public final static int MAX_PRIORITY = 10;4、native方法(非java应用)
//获得当前的线程 public static native Thread currentThread(); //礼让线程,会放弃当前的运行状态变为就绪状态去重新竞争执行 public static native void yield(); //休眠,让线程停止多少时间再次执行 public static native void sleep(long millis) throws InterruptedException; //开始线程 private native void start0(); //调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态 private native boolean isInterrupted(boolean ClearInterrupted); //判断线程是否存活 public final native boolean isAlive(); //@Deprecated注解的意思是不推荐使用,就不解释意思了 @Deprecated public native int countStackFrames(); //当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。 public static native boolean holdsLock(Object obj); //设置线程优先级 private native void setPriority0(int newPriority); //停止线程 private native void stop0(Object o); //线程挂起(暂停) private native void suspend0(); //将一个挂起线程复活继续执行 private native void resume0(); //该线程的中断状态将被设置 private native void interrupt0(); //没找到解释,字面意思是写入native的名称 private native void setNativeName(String name);5、Thread的构造方法
//默认的什么都不传 public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); } //target被调用RUN方法的目标对象 public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); } //设置了线程分组并传递了被调用RUN方法的目标对象 public Thread(ThreadGroup group, Runnable target) { init(group, target, "Thread-" + nextThreadNum(), 0); } //只设置了线程名称 public Thread(String name) { init(null, null, name, 0); } //设置了线程分组和线程名称 public Thread(ThreadGroup group, String name) { init(group, null, name, 0); } //传递了调用RUN方法的目标对象并设置了线程名称 public Thread(Runnable target, String name) { init(null, target, name, 0); } //传递了调用RUN方法的目标对象并设置了线程分组和线程名称 public Thread(ThreadGroup group, Runnable target, String name) { init(group, target, name, 0); } //传递了调用RUN方法的目标对象并设置了线程分组和线程名称和堆栈大小 public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { init(group, target, name, stackSize); }6、普通方法
//millis为毫秒,nanos为纳秒,1000纳秒=1毫秒,其他跟sleep方法一样 public static void sleep(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } sleep(millis); } //init初始化,线程的初始化方法,g = 分组 target = 调用run的对象 name = 线程名称 stackSize = 设置的堆栈大小 private void init(ThreadGroup g, Runnable target, String name, long stackSize) { init(g, target, name, stackSize, null, true); } private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { //如果线程名称为空 if (name == null) { throw new NullPointerException("name cannot be null"); } //设置volatile的name为传递name this.name = name; //获得当前线程 Thread parent = currentThread(); //获得系统的安全管理器 SecurityManager security = System.getSecurityManager(); if (g == null) { //安全检查 if (security != null) { g = security.getThreadGroup(); } //设置线程组 if (g == null) { g = parent.getThreadGroup(); } } //检查是否允许调用线程修改线程组参数 g.checkAccess(); //是否有权限访问 if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } //往线程组添加线程但未启动 g.addUnstarted(); //线程组 this.group = g; //是否守护线程 this.daemon = parent.isDaemon(); //优先级 this.priority = parent.getPriority(); //每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。 if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext(); this.target = target; setPriority(priority); if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); } //克隆。构造一个新线程。 @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } //使线程进入可执行(runnable状态)的状态 public synchronized void start() { //验证线程的状态,如果线程已启动则抛异常 if (threadStatus != 0) throw new IllegalThreadStateException(); //向线程组里添加此线程 group.add(this); boolean started = false; try { //使线程进入可执行(runnable状态)的状态 start0(); //设置状态为true started = true; } finally { try { //如果状态不为true,此线程启动失败 if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } //使线程从可运行状态转化为运行状态 @Override public void run() { if (target != null) { target.run(); } } //这个方法是在Run方法执行结束后用于结束线程的。通过单步调试一个线程发现执行完run方法之后会进入exit方法。 private void exit() { if (group != null) { group.threadTerminated(this); group = null; } /* Aggressively null out all reference fields: see bug 4006245 */ target = null; /* Speed the release of some of these resources */ threadLocals = null; inheritableThreadLocals = null; inheritedAccessControlContext = null; blocker = null; uncaughtExceptionHandler = null; } //@Deprecated不建议使用 //停止线程 @Deprecated public final void stop() { SecurityManager security = System.getSecurityManager(); //如果安全管理器不为空 if (security != null) { //检查是否允许调用线程修改线程组参数 checkAccess(); //如果这个线程不是当前线程或者这个线程以销毁 if (this != Thread.currentThread()) { //如果所请求的访问,通过给定的权限,指定的安全策略不允许根据当前有效的方法将抛出一个SecurityException。 security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } //如果线程已启动 if (threadStatus != 0) { //如果线程被挂起则唤醒 resume(); } //停止线程 stop0(new ThreadDeath()); } //@Deprecated不建议使用 //停止线程 @Deprecated public final synchronized void stop(Throwable obj) { throw new UnsupportedOperationException(); } //中断此线程(阻塞)但实际上只是给线程设置一个中断标志,线程仍会继续运行。 public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(this); return; } } interrupt0(); } //测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。 public static boolean interrupted() { return currentThread().isInterrupted(true); } //只测试此线程是否被中断 ,不清除中断状态。 public boolean isInterrupted() { return isInterrupted(false); } private native boolean isInterrupted(boolean ClearInterrupted); //@Deprecated不建议使用 //销毁线程组及其所有子组。 线程组必须为空,表示线程组中的所有线程都已停止。 @Deprecated public void destroy() { throw new NoSuchMethodError(); } //@Deprecated不建议使用 //暂停线程直到被唤醒 而Abort强制杀死线程 @Deprecated public final void suspend() { checkAccess(); suspend0(); } //@Deprecated不建议使用 //如果线程被挂起则唤醒 @Deprecated public final void resume() { checkAccess(); resume0(); } //设置线程的优先级 public final void setPriority(int newPriority) { ThreadGroup g; //检查是否允许调用线程修改线程组参数 checkAccess(); //如果设置的优先级大于最大优先级或者小于最小的优先级抛异常 if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) { throw new IllegalArgumentException(); } if((g = getThreadGroup()) != null) { if (newPriority > g.getMaxPriority()) { newPriority = g.getMaxPriority(); } setPriority0(priority = newPriority); } } //获得线程的优先级 public final int getPriority() { return priority; } //设置线程名称 public final synchronized void setName(String name) { checkAccess(); if (name == null) { throw new NullPointerException("name cannot be null"); } this.name = name; if (threadStatus != 0) { setNativeName(name); } } //获取线程名称 public final String getName() { return name; } //获得当前的线程的线程组 public final ThreadGroup getThreadGroup() { return group; } //获得当前线程组中还在活动中的线程数 public static int activeCount() { return currentThread().getThreadGroup().activeCount(); } //将这个线程组中存活的线程全部复制到预设置好的数组中 public static int enumerate(Thread tarray[]) { return currentThread().getThreadGroup().enumerate(tarray); } //@Deprecated不建议使用 @Deprecated public native int countStackFrames(); //堵塞当前线程,使其处于等待状态,因为子线程执行的时间可能比主线程执行时间还长,所以join是主线程需要在它执行完后再销毁。当然也可以加参数join(long millis, int nanos),使其等待N秒N毫秒,如果它已经处于join方法,则报InterruptedException 。 public final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } } public final synchronized void join(long millis, int nanos) throws InterruptedException { if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (nanos < 0 || nanos > 999999) { throw new IllegalArgumentException( "nanosecond timeout value out of range"); } if (nanos >= 500000 || (nanos != 0 && millis == 0)) { millis++; } join(millis); } public final void join() throws InterruptedException { join(0); } //将当前线程的堆栈跟踪打印至标准错误流 public static void dumpStack() { new Exception("Stack trace").printStackTrace(); } /设置线程为守护线程 public final void setDaemon(boolean on) { //检查是否允许调用线程修改线程组参数 checkAccess(); //首先先去确认此线程是否处于活动状态,如果处于活动状态则抛异常 if (isAlive()) { throw new IllegalThreadStateException(); } //将其设置为守护线程 daemon = on; } //确认线程是否是守护线程 public final boolean isDaemon() { return daemon; } //检查是否允许调用线程修改线程组参数 public final void checkAccess() { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkAccess(this); } } 返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 public String toString() { ThreadGroup group = getThreadGroup(); if (group != null) { return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]"; } else { return "Thread[" + getName() + "," + getPriority() + "," + "" + "]"; } } //@CallerSensitive注解:jdk内有些方法,jvm的开发者认为这些方法危险,不希望开发者调用,就把这种危险的方法用@CallerSensitive修饰,并在“jvm”级别检查。 //返回该线程的上下文 ClassLoader。上下文 ClassLoader 由线程创建者提供,供运行于该线程中的代码在加载类和资源时使用。如果未设定,则默认为父线程的 ClassLoader 上下文。原始线程的上下文 ClassLoader 通常设定为用于加载应用程序的类加载器。 //首先,如果有安全管理器,并且调用者的类加载器不是 null,也不同于其上下文类加载器正在被请求的线程上下文类加载器的祖先,则通过 RuntimePermission("getClassLoader") 权限调用该安全管理器的 checkPermission 方法,查看是否可以获取上下文 ClassLoader。 @CallerSensitive public ClassLoader getContextClassLoader() { if (contextClassLoader == null) return null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { ClassLoader.checkClassLoaderPermission(contextClassLoader, Reflection.getCallerClass()); } return contextClassLoader; } //设置该线程的上下文 ClassLoader。上下文 ClassLoader 可以在创建线程设置,并允许创建者在加载类和资源时向该线程中运行的代码提供适当的类加载器。 //首先,如果有安全管理器,则通过 RuntimePermission("setContextClassLoader") 权限调用其 checkPermission 方法,查看是否可以设置上下文 ClassLoader。 public void setContextClassLoader(ClassLoader cl) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("setContextClassLoader")); } contextClassLoader = cl; } // 返回一个表示该线程堆栈转储的堆栈跟踪元素数组。 public StackTraceElement[] getStackTrace() { if (this != Thread.currentThread()) { // check for getStackTrace permission SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission( SecurityConstants.GET_STACK_TRACE_PERMISSION); } // optimization so we do not call into the vm for threads that // have not yet started or have terminated if (!isAlive()) { return EMPTY_STACK_TRACE; } StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this}); StackTraceElement[] stackTrace = stackTraceArray[0]; // a thread that was alive during the previous isAlive call may have // since terminated, therefore not having a stacktrace. if (stackTrace == null) { stackTrace = EMPTY_STACK_TRACE; } return stackTrace; } else { // Don't need JVM help for current thread return (new Exception()).getStackTrace(); } } //返回所有活动线程的堆栈跟踪的一个映射。 public static Map<Thread, StackTraceElement[]> getAllStackTraces() { // check for getStackTrace permission SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkPermission( SecurityConstants.GET_STACK_TRACE_PERMISSION); security.checkPermission( SecurityConstants.MODIFY_THREADGROUP_PERMISSION); } // Get a snapshot of the list of all threads Thread[] threads = getThreads(); StackTraceElement[][] traces = dumpThreads(threads); Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length); for (int i = 0; i < threads.length; i++) { StackTraceElement[] stackTrace = traces[i]; if (stackTrace != null) { m.put(threads[i], stackTrace); } // else terminated so we don't put it in the map } return m; } //安全审计结果缓存的子类 //将来的版本中替换为ConcurrentReferenceHashMap private static class Caches { /** cache of subclass security audit results */ static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = new ConcurrentHashMap<>(); /** queue for WeakReferences to audited subclasses */ static final ReferenceQueue<Class<?>> subclassAuditsQueue = new ReferenceQueue<>(); } //验证这个子类实例是否可以被构造,在不违反安全约束:子类不能覆盖 private static boolean isCCLOverridden(Class<?> cl) { if (cl == Thread.class) return false; processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits); WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue); Boolean result = Caches.subclassAudits.get(key); if (result == null) { result = Boolean.valueOf(auditSubclass(cl)); Caches.subclassAudits.putIfAbsent(key, result); } return result.booleanValue(); } //对给定的子类执行反射检查以验证它不是覆盖安全敏感的非final方法,如果子类重写任何方法,返回true否则返回false private static boolean auditSubclass(final Class<?> subcl) { Boolean result = AccessController.doPrivileged( new PrivilegedAction<Boolean>() { public Boolean run() { for (Class<?> cl = subcl; cl != Thread.class; cl = cl.getSuperclass()) { try { cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]); return Boolean.TRUE; } catch (NoSuchMethodException ex) { } try { Class<?>[] params = {ClassLoader.class}; cl.getDeclaredMethod("setContextClassLoader", params); return Boolean.TRUE; } catch (NoSuchMethodException ex) { } } return Boolean.FALSE; } } ); return result.booleanValue(); } //获取线程ID public long getId() { return tid; } //枚举,线程状态 public enum State { //新建(new) NEW, //可运行(Runnable) RUNNABLE, //阻塞(block) BLOCKED, //无限期等待(waiting) WAITING, //限期等待(TIMED_WAITING) TIMED_WAITING, //结束(terminated) TERMINATED; }调用线程的start()方法,线程进入可运行状态(Runnable)
Java线程中的Runnable状态包括操作系统线程的running和ready状态,处于就绪状态的线程一旦获得CPU使用权,进入运行状态
即处于Runnable状态的线程可能正在运行,也可能正在等待CPU分配时间片
调用Thread类的start()方法之后
一个线程处于等待(waiting)状态,表示该线程正在等待其它线程执行特定的操作
例如,一个线程调用了Object类的空参的wait方法,表示该线程等待其它线程调用该对象的notify或者notifyAll方法
一个线程调用了Thread类的空参的join方法,表示该线程在等待一个特定的线程终止
何时进入waiting状态:
调用Object类空参的wait()
调用Thread类空参的join()
一个线程在执行过程中,想获得某一资源的锁,但是该资源又被其它线程占用,此时,当前线程处于阻塞状态(例如,进入一个同步方法或者同步代码块,要先获得锁)
阻塞和等待的不同是,阻塞状态是在等待一个排它锁
等待状态实在等待一个事件的发生,如等待时间到,唤醒方法被调用
一个线程处于超时等待状态(timed_waiting),和waiting不同的是,将在特定的时间内自行返回
何时进入timed_waiting状态:
调用Object类有参的wait()
调用Thread类有参的join()
调用Thread类的sleep方法(sleep方法没有空参的重载形式)
一个线程执行完毕,进入终止状态(terminated)
线程执行完毕
线程在执行过程中抛出异常
//获取线程状态 public State getState() { // get current thread state return sun.misc.VM.toThreadState(threadStatus); } //@FunctionalInterface 函数式接口 //记录错误日志,即对未知异常的处理 @FunctionalInterface public interface UncaughtExceptionHandler { /** * Method invoked when the given thread terminates due to the * given uncaught exception. * <p>Any exception thrown by this method will be ignored by the * Java Virtual Machine. * @param t the thread * @param e the exception */ void uncaughtException(Thread t, Throwable e); } //某段代码做try … catch 没有catch到的代码,发生异常的时候,就会由它来处理。 public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission( new RuntimePermission("setDefaultUncaughtExceptionHandler") ); } defaultUncaughtExceptionHandler = eh; } //获取异常信息 public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ return defaultUncaughtExceptionHandler; } //查询线程的UncaughtExceptionHandler并将线程和异常作为参数传递给handler的uncaughtException()方法进行处理。 public UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group; } //存入UncaughtExceptionHandler信息 public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { checkAccess(); uncaughtExceptionHandler = eh; } //线程出现未捕获异常后,JVM将调用Thread中的dispatchUncaughtException方法把异常传递给线程的未捕获异常处理器。 private void dispatchUncaughtException(Throwable e) { getUncaughtExceptionHandler().uncaughtException(this, e); } //从指定的映射中移除指定引用队列中已排队的任何键 static void processQueue(ReferenceQueue<Class<?>> queue, ConcurrentMap<? extends WeakReference<Class<?>>, ?> map) { Reference<? extends Class<?>> ref; while((ref = queue.poll()) != null) { map.remove(ref); } } //类对象的弱键 static class WeakClassKey extends WeakReference<Class<?>> { /** * saved value of the referent's identity hash code, to maintain * a consistent hash code after the referent has been cleared */ private final int hash; /** * Create a new WeakClassKey to the given object, registered * with a queue. */ WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) { super(cl, refQueue); hash = System.identityHashCode(cl); } /** * Returns the identity hash code of the original referent. */ @Override public int hashCode() { return hash; } /** * Returns true if the given object is this identical * WeakClassKey instance, or, if this object's referent has not * been cleared, if the given object is another WeakClassKey * instance with the identical non-null referent as this one. */ @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj instanceof WeakClassKey) { Object referent = get(); return (referent != null) && (referent == ((WeakClassKey) obj).get()); } else { return false; } } }