aboutsummaryrefslogtreecommitdiffstats
path: root/org.aspectj.matcher/src/main/java/org/aspectj/weaver/WeakClassLoaderReference.java
blob: 9d81873a719498d946ab63a270c3b928a400accd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/* *******************************************************************
 * Copyright (c) 2008 Contributors
 * All rights reserved.
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Public License v 2.0
 * which accompanies this distribution and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
 *
 * Contributors:
 *     Andy Clement     initial implementation
 * ******************************************************************/
package org.aspectj.weaver;

import java.lang.ref.WeakReference;

/**
 * Wraps a reference to a classloader inside a WeakReference. This should be used where we do not want the existence of a
 * classloader reference to prevent garbage collection of that classloader (and possibly an associated weaver instance in the case
 * of load time weaving).
 * <p>
 * In more detail:<br>
 * When load time weaving, the class Aj maintains a WeakHashMap from the classloader instance to a weaver instance. The aim is that
 * the weaver is around as long as the classloader is and should the classloader be dereferenced then the weaver can also be garbage
 * collected. The problem is that if there are many references to the classloader from within the weaver, these are considered hard
 * references and cause the classloader to be long lived - even if the user of the classloader has dereferenced it in their code.
 * The solution is that the weaver should use instances of WeakClassLoaderReference objects - so that when the users hard reference
 * to the classloader goes, nothing in the weaver will cause it to hang around. There is a big assertion here that the
 * WeakClassLoaderReference instances will not 'lose' their ClassLoader references until the top level ClassLoader reference is
 * null'd. This means there is no need to check for the null case on get() in this WeakReference logic below, because we shouldn't
 * be using this weaver if its associated ClassLoader has been collected. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=210470
 *
 *
 * @author Andy Clement, Abraham Nevado
 */
public class WeakClassLoaderReference{

	protected final int hashcode;

	private final WeakReference<ClassLoader> loaderRef;

	public WeakClassLoaderReference(ClassLoader loader) {
		loaderRef = new WeakReference<>(loader);
		if(loader == null){
			// Bug: 363962
			// Check that ClassLoader is not null, for instance when loaded from BootStrapClassLoader
			hashcode = System.identityHashCode(this);
		}else{
			hashcode = loader.hashCode() * 37;
		}
	}

	public ClassLoader getClassLoader() {
		ClassLoader instance = loaderRef.get();
		// Assert instance!=null
		return instance;
	}

	public boolean equals(Object obj) {
		if (!(obj instanceof WeakClassLoaderReference))
			return false;
		WeakClassLoaderReference other = (WeakClassLoaderReference) obj;
		return (other.hashcode == hashcode);
	}

	public int hashCode() {
		return hashcode;
	}

}