Removed ThreadLocals class and its references, since it is no longer needed.

This commit is contained in:
Martijn van Groningen 2013-09-03 17:57:11 +02:00
parent b39961b2a6
commit d5a47e597d
3 changed files with 0 additions and 164 deletions

View File

@ -69,7 +69,6 @@ import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.util.concurrent.ThreadLocals;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.EnvironmentModule;
import org.elasticsearch.monitor.MonitorService;
@ -283,7 +282,6 @@ public class TransportClient extends AbstractClient {
injector.getInstance(CacheRecycler.class).close();
CachedStreams.clear();
ThreadLocals.clearReferencesThreadLocals();
}
@Override

View File

@ -1,160 +0,0 @@
/*
* Licensed to ElasticSearch and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. ElasticSearch licenses this
* file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.util.concurrent;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
*
*/
public class ThreadLocals {
private static final ESLogger logger = Loggers.getLogger(ThreadLocals.class);
public static void clearReferencesThreadLocals() {
try {
Thread[] threads = getThreads();
// Make the fields in the Thread class that store ThreadLocals
// accessible
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
inheritableThreadLocalsField.setAccessible(true);
// Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects
// accessible
Class<?> tlmClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = tlmClass.getDeclaredField("table");
tableField.setAccessible(true);
for (int i = 0; i < threads.length; i++) {
Object threadLocalMap;
if (threads[i] != null) {
// Clear the first map
threadLocalMap = threadLocalsField.get(threads[i]);
clearThreadLocalMap(threadLocalMap, tableField);
// Clear the second map
threadLocalMap =
inheritableThreadLocalsField.get(threads[i]);
clearThreadLocalMap(threadLocalMap, tableField);
}
}
} catch (Exception e) {
logger.debug("failed to clean thread locals", e);
}
}
/*
* Clears the given thread local map object. Also pass in the field that
* points to the internal table to save re-calculating it on every
* call to this method.
*/
private static void clearThreadLocalMap(Object map, Field internalTableField) throws NoSuchMethodException, IllegalAccessException, NoSuchFieldException, InvocationTargetException {
if (map != null) {
Method mapRemove = map.getClass().getDeclaredMethod("remove", ThreadLocal.class);
mapRemove.setAccessible(true);
Object[] table = (Object[]) internalTableField.get(map);
int staleEntriesCount = 0;
if (table != null) {
for (int j = 0; j < table.length; j++) {
Object tableValue = table[j];
if (tableValue != null) {
boolean remove = false;
// Check the key
Object key = ((Reference<?>) tableValue).get();
// Check the value
Field valueField = tableValue.getClass().getDeclaredField("value");
valueField.setAccessible(true);
Object value = valueField.get(tableValue);
if (value != null) {
Object actualValue = value;
if (value instanceof SoftReference) {
actualValue = ((SoftReference) value).get();
}
if (actualValue != null) {
String actualValueClassName = actualValue.getClass().getName();
if (actualValueClassName.startsWith("org.elasticsearch") || actualValueClassName.startsWith("org.apache.lucene")) {
remove = true;
}
}
}
if (remove) {
Object[] args = new Object[4];
if (key != null) {
args[0] = key.getClass().getCanonicalName();
args[1] = key.toString();
}
args[2] = value.getClass().getCanonicalName();
args[3] = value.toString();
if (logger.isTraceEnabled()) {
logger.trace("ThreadLocal with key of type [{}] (value [{}]) and a value of type [{}] (value [{}]): The ThreadLocal has been forcibly removed.", args);
}
if (key == null) {
staleEntriesCount++;
} else {
mapRemove.invoke(map, key);
}
}
}
}
}
if (staleEntriesCount > 0) {
Method mapRemoveStale = map.getClass().getDeclaredMethod("expungeStaleEntries");
mapRemoveStale.setAccessible(true);
mapRemoveStale.invoke(map);
}
}
}
/*
* Get the set of current threads as an array.
*/
private static Thread[] getThreads() {
// Get the current thread group
ThreadGroup tg = Thread.currentThread().getThreadGroup();
// Find the root thread group
while (tg.getParent() != null) {
tg = tg.getParent();
}
int threadCountGuess = tg.activeCount() + 50;
Thread[] threads = new Thread[threadCountGuess];
int threadCountActual = tg.enumerate(threads);
// Make sure we don't miss any threads
while (threadCountActual == threadCountGuess) {
threadCountGuess *= 2;
threads = new Thread[threadCountGuess];
// Note tg.enumerate(Thread[]) silently ignores any threads that
// can't fit into the array
threadCountActual = tg.enumerate(threads);
}
return threads;
}
}

View File

@ -51,7 +51,6 @@ import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.util.concurrent.ThreadLocals;
import org.elasticsearch.discovery.Discovery;
import org.elasticsearch.discovery.DiscoveryModule;
import org.elasticsearch.discovery.DiscoveryService;
@ -361,7 +360,6 @@ public final class InternalNode implements Node {
Injectors.close(injector);
CachedStreams.clear();
ThreadLocals.clearReferencesThreadLocals();
logger.info("closed");
}