improve clearing caches in guice

This commit is contained in:
kimchy 2011-07-01 13:32:23 +03:00
parent a51f86aeb1
commit bac6240d17
4 changed files with 21 additions and 57 deletions

View File

@ -45,7 +45,7 @@ class InheritingState implements State {
private final Map<Class<? extends Annotation>, Scope> scopes = Maps.newHashMap();
private final List<MatcherAndConverter> converters = Lists.newArrayList();
private final List<TypeListenerBinding> listenerBindings = Lists.newArrayList();
private final WeakKeySet blacklistedKeys = new WeakKeySet();
private WeakKeySet blacklistedKeys = new WeakKeySet();
private final Object lock;
InheritingState(State parent) {
@ -126,6 +126,10 @@ class InheritingState implements State {
return blacklistedKeys.contains(key);
}
@Override public void clearBlacklisted() {
blacklistedKeys = new WeakKeySet();
}
public Object lock() {
return lock;
}

View File

@ -57,7 +57,7 @@ class InjectorImpl implements Injector, Lookups {
/**
* Just-in-time binding cache. Guarded by state.lock()
*/
final Map<Key<?>, BindingImpl<?>> jitBindings = Maps.newHashMap();
Map<Key<?>, BindingImpl<?>> jitBindings = Maps.newHashMap();
Lookups lookups = new DeferredLookups(this);
@ -723,7 +723,7 @@ class InjectorImpl implements Injector, Lookups {
/**
* Cached constructor injectors for each type
*/
final ConstructorInjectorStore constructors = new ConstructorInjectorStore(this);
ConstructorInjectorStore constructors = new ConstructorInjectorStore(this);
/**
* Cached field and method injectors for each type.
@ -830,4 +830,11 @@ class InjectorImpl implements Injector, Lookups {
.toString();
}
// ES_GUICE: clear caches
public void clearCache() {
state.clearBlacklisted();
constructors = new ConstructorInjectorStore(this);
membersInjectorStore = new MembersInjectorStore(this, state.getTypeListenerBindings());
jitBindings = Maps.newHashMap();
}
}

View File

@ -19,12 +19,10 @@
package org.elasticsearch.common.inject;
import org.elasticsearch.ElasticSearchIllegalStateException;
import org.elasticsearch.common.collect.Sets;
import org.elasticsearch.common.inject.matcher.Matcher;
import org.elasticsearch.common.inject.name.Names;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Map.Entry;
@ -224,58 +222,7 @@ public class Injectors {
}
public static void cleanCaches(Injector injector) {
// clean blacklist, it becomes really big, and it can always get regenerated if needed
try {
Field stateField = injector.getClass().getDeclaredField("state");
stateField.setAccessible(true);
Object state = stateField.get(injector);
if (state.getClass().getName().contains("InheritingState")) {
Field blacklistedKeysField = state.getClass().getDeclaredField("blacklistedKeys");
blacklistedKeysField.setAccessible(true);
Object blacklistedKeys = blacklistedKeysField.get(state);
Field backingSetField = blacklistedKeys.getClass().getDeclaredField("backingSet");
backingSetField.setAccessible(true);
((Set) backingSetField.get(blacklistedKeys)).clear();
}
} catch (Exception e) {
throw new ElasticSearchIllegalStateException("Failed to clear state from injector", e);
}
// clean constructors cache
try {
Field constructorsField = injector.getClass().getDeclaredField("constructors");
constructorsField.setAccessible(true);
Object constructors = constructorsField.get(injector);
Field cacheField = constructors.getClass().getDeclaredField("cache");
cacheField.setAccessible(true);
Object cache = cacheField.get(constructors);
Field delegateField = cache.getClass().getSuperclass().getDeclaredField("delegate");
delegateField.setAccessible(true);
((Map) delegateField.get(cache)).clear();
} catch (Exception e) {
throw new ElasticSearchIllegalStateException("Failed to clear constructors cache from injector", e);
}
// clean method cache
try {
Field membersField = injector.getClass().getDeclaredField("membersInjectorStore");
membersField.setAccessible(true);
Object members = membersField.get(injector);
if (members != null) {
Field cacheField = members.getClass().getDeclaredField("cache");
cacheField.setAccessible(true);
Object cache = cacheField.get(members);
Field delegateField = cache.getClass().getSuperclass().getDeclaredField("delegate");
delegateField.setAccessible(true);
((Map) delegateField.get(cache)).clear();
}
} catch (Exception e) {
throw new ElasticSearchIllegalStateException("Failed to clear constructors cache from injector", e);
}
((InjectorImpl) injector).clearCache();
if (injector.getParent() != null) {
cleanCaches(injector.getParent());
}

View File

@ -88,6 +88,9 @@ interface State {
return true;
}
@Override public void clearBlacklisted() {
}
public Object lock() {
throw new UnsupportedOperationException();
}
@ -149,4 +152,7 @@ interface State {
* to be used when reading mutable data (ie. just-in-time bindings, and binding blacklists).
*/
Object lock();
// ES_GUICE: clean blacklist keys
void clearBlacklisted();
}