All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.zving.preloader.ReferenceCleaner Maven / Gradle / Ivy
package com.zving.preloader;
import java.beans.Introspector;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
public class ReferenceCleaner
{
private static final List JVM_THREAD_GROUP_NAMES = new ArrayList();
private static final String JVN_THREAD_GROUP_SYSTEM = "system";
private PreClassLoader loader;
static
{
JVM_THREAD_GROUP_NAMES.add("system");
JVM_THREAD_GROUP_NAMES.add("RMI Runtime");
}
public ReferenceCleaner(PreClassLoader loader)
{
this.loader = loader;
}
protected void clearReferences()
{
clearReferencesJdbc();
clearReferencesThreads();
clearReferencesThreadLocals();
clearReferencesRmiTargets();
clearReferencesStaticFinal();
try
{
Class> clazz = Class.forName("org.apache.commons.logging.LogFactory");
if (clazz != null)
{
Method m = clazz.getMethod("release", new Class[] { ClassLoader.class });
m.invoke(null, new Object[] { this.loader });
}
}
catch (Exception localException) {}
clearReferencesResourceBundles();
Introspector.flushCaches();
this.loader = null;
}
private final void clearReferencesJdbc()
{
InputStream is;
byte classBytes[];
int offset;
is = loader.getResourceAsStream("com/zving/preloader/JdbcLeakPrevention.class");
classBytes = new byte[2048];
offset = 0;
try
{
for(int read = is.read(classBytes, offset, classBytes.length - offset); read > -1; read = is.read(classBytes, offset, classBytes.length - offset))
{
offset += read;
if(offset == classBytes.length)
{
byte tmp[] = new byte[classBytes.length * 2];
System.arraycopy(classBytes, 0, tmp, 0, classBytes.length);
classBytes = tmp;
}
}
Class lpClass = loader.defineClassEx("com.zving.preloader.JdbcLeakPrevention", classBytes, 0, offset, getClass().getProtectionDomain());
Object obj = lpClass.newInstance();
List driverNames = (List)obj.getClass().getMethod("clearJdbcDriverRegistrations", new Class[0]).invoke(obj, new Object[0]);
String name;
for(Iterator iterator = driverNames.iterator(); iterator.hasNext(); System.out.println((new StringBuilder("Clear JDBC reference success:")).append(name).toString()))
name = (String)iterator.next();
}
catch(Exception e)
{
System.out.println((new StringBuilder("Clear JDBC reference failed:")).append(e.getMessage()).toString());
}
if(is != null)
try
{
is.close();
}
catch(IOException ioexception) { }
}
private final void clearReferencesStaticFinal()
{
Class[] arr = new Class[this.loader.getLoadedClasses().size()];
arr = (Class[])this.loader.getLoadedClasses().toArray(arr);
Class[] arrayOfClass1;
int j = (arrayOfClass1 = arr).length;
for (int k = 0; k < j; k++)
{
Class> clazz = arrayOfClass1[k];
try
{
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
if (Modifier.isStatic(fields[i].getModifiers()))
{
fields[i].get(null);
break;
}
}
}
catch (Throwable localThrowable1) {}
}
j = (arrayOfClass1 = arr).length;
for (Class> clazz: arrayOfClass1)
{
// Class> clazz = arrayOfClass1[i];
try
{
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++)
{
Field field = fields[i];
int mods = field.getModifiers();
if ((!field.getType().isPrimitive()) && (field.getName().indexOf("$") == -1)) {
if (Modifier.isStatic(mods)) {
try
{
field.setAccessible(true);
if (Modifier.isFinal(mods))
{
if ((!field.getType().getName().startsWith("java.")) && (!field.getType().getName().startsWith("javax."))) {
nullInstance(field.get(null));
}
}
else {
field.set(null, null);
}
}
catch (Throwable localThrowable2) {}
}
}
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
}
private void nullInstance(Object instance)
{
if (instance == null) {
return;
}
Field[] fields = instance.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++)
{
Field field = fields[i];
int mods = field.getModifiers();
if ((!field.getType().isPrimitive()) && (field.getName().indexOf("$") == -1)) {
try
{
field.setAccessible(true);
if ((!Modifier.isStatic(mods)) || (!Modifier.isFinal(mods)))
{
Object value = field.get(instance);
if (value != null)
{
Class extends Object> valueClass = value.getClass();
if (loadedByThisOrChild(valueClass)) {
field.set(instance, null);
}
}
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
}
}
protected boolean loadedByThisOrChild(Class> clazz)
{
boolean result = false;
for (ClassLoader classLoader = clazz.getClassLoader(); classLoader != null; classLoader = classLoader.getParent()) {
if (classLoader.equals(this))
{
result = true;
break;
}
}
return result;
}
private boolean threadNeedClear(Thread thread)
{
if (thread == Thread.currentThread()) {
return false;
}
ThreadGroup tg = thread.getThreadGroup();
if ((tg != null) && (JVM_THREAD_GROUP_NAMES.contains(tg.getName())))
{
if (thread.getName().equals("Keep-Alive-Timer")) {
thread.setContextClassLoader(this.loader.getParent());
}
return false;
}
if (!thread.isAlive()) {
return false;
}
if (thread.getContextClassLoader() == this.loader) {
return true;
}
if (thread.getClass().getClassLoader() == this.loader) {
return true;
}
Object target = null;
String[] arrayOfString;
int j = (arrayOfString = new String[] { "target", "runnable", "action" }).length;
for (int i = 0; i < j; i++)
{
String fieldName = arrayOfString[i];
try
{
Field targetField = thread.getClass().getDeclaredField(fieldName);
targetField.setAccessible(true);
target = targetField.get(thread);
}
catch (Exception localException) {}
}
if ((target != null) && (target.getClass().getClassLoader() == this.loader)) {
return true;
}
return false;
}
private void clearReferencesThreads()
{
Thread[] threads = getThreads();
Thread[] arrayOfThread1;
int j = (arrayOfThread1 = threads).length;
for (int i = 0; i < j; i++)
{
Thread thread = arrayOfThread1[i];
if (thread != null)
{
boolean clear = threadNeedClear(thread);
if (clear) {
if (thread.getClass().getName().startsWith("java.util.Timer"))
{
clearReferencesStopTimerThread(thread);
}
else
{
try
{
Object target = null;
String[] arrayOfString;
int m = (arrayOfString = new String[] { "target", "runnable", "action" }).length;
for (int k = 0; k < m; k++)
{
String fieldName = arrayOfString[k];
try
{
Field targetField = thread.getClass().getDeclaredField(fieldName);
targetField.setAccessible(true);
target = targetField.get(thread);
}
catch (NoSuchFieldException localNoSuchFieldException) {}
}
if ((target != null) &&
(target.getClass().getCanonicalName() != null) &&
(target.getClass().getCanonicalName().equals("java.util.concurrent.ThreadPoolExecutor.Worker")))
{
Field executorField = target.getClass().getDeclaredField("this$0");
executorField.setAccessible(true);
Object executor = executorField.get(target);
if ((executor instanceof ThreadPoolExecutor)) {
((ThreadPoolExecutor)executor).shutdownNow();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
thread.notifyAll();
thread.interrupt();
}
catch (Throwable localThrowable) {}
try
{
thread.stop();
}
catch (Throwable localThrowable1) {}
}
}
}
}
}
private void clearReferencesStopTimerThread(Thread thread)
{
try
{
try
{
Field newTasksMayBeScheduledField = thread.getClass().getDeclaredField("newTasksMayBeScheduled");
newTasksMayBeScheduledField.setAccessible(true);
Field queueField = thread.getClass().getDeclaredField("queue");
queueField.setAccessible(true);
Object queue = queueField.get(thread);
Method clearMethod = queue.getClass().getDeclaredMethod("clear", new Class[0]);
clearMethod.setAccessible(true);
synchronized (queue)
{
newTasksMayBeScheduledField.setBoolean(thread, false);
clearMethod.invoke(queue, new Object[0]);
queue.notify();
}
}
catch (NoSuchFieldException nfe)
{
Method cancelMethod = thread.getClass().getDeclaredMethod("cancel", new Class[0]);
synchronized (thread)
{
cancelMethod.setAccessible(true);
cancelMethod.invoke(thread, new Object[0]);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void clearReferencesThreadLocals()
{
Thread[] threads = getThreads();
try
{
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Field inheritableThreadLocalsField = Thread.class.getDeclaredField("inheritableThreadLocals");
inheritableThreadLocalsField.setAccessible(true);
Class> tlmClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = tlmClass.getDeclaredField("table");
tableField.setAccessible(true);
Method expungeStaleEntriesMethod = tlmClass.getDeclaredMethod("expungeStaleEntries", new Class[0]);
expungeStaleEntriesMethod.setAccessible(true);
for (int i = 0; i < threads.length; i++) {
if (threads[i] != null)
{
Object threadLocalMap = threadLocalsField.get(threads[i]);
if (threadLocalMap != null)
{
expungeStaleEntriesMethod.invoke(threadLocalMap, new Object[0]);
checkThreadLocalMapForLeaks(threadLocalMap, tableField);
}
threadLocalMap = inheritableThreadLocalsField.get(threads[i]);
if (threadLocalMap != null)
{
expungeStaleEntriesMethod.invoke(threadLocalMap, new Object[0]);
checkThreadLocalMapForLeaks(threadLocalMap, tableField);
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void checkThreadLocalMapForLeaks(Object map, Field internalTableField)
throws NoSuchMethodException, IllegalAccessException, NoSuchFieldException, InvocationTargetException
{
if (map != null)
{
Method mapRemove = map.getClass().getDeclaredMethod("remove", new Class[] { 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++) {
if (table[j] != null)
{
boolean remove = false;
Object key = ((Reference)table[j]).get();
if ((equals(key)) || (isLoadedByThisWebappClassLoader(key))) {
remove = true;
}
Field valueField = table[j].getClass().getDeclaredField("value");
valueField.setAccessible(true);
Object value = valueField.get(table[j]);
if ((equals(value)) || (isLoadedByThisWebappClassLoader(value))) {
remove = true;
}
if (remove) {
if (key == null) {
staleEntriesCount++;
} else {
mapRemove.invoke(map, new Object[] { key });
}
}
}
}
}
if (staleEntriesCount > 0)
{
Method mapRemoveStale = map.getClass().getDeclaredMethod("expungeStaleEntries", new Class[0]);
mapRemoveStale.setAccessible(true);
mapRemoveStale.invoke(map, new Object[0]);
}
}
}
private boolean isLoadedByThisWebappClassLoader(Object o)
{
if (o == null) {
return false;
}
for (ClassLoader loader = o.getClass().getClassLoader(); loader != null; loader = loader.getParent()) {
if (loader == this.loader) {
return true;
}
}
return false;
}
private Thread[] getThreads()
{
ThreadGroup tg = Thread.currentThread().getThreadGroup();
while (tg.getParent() != null) {
tg = tg.getParent();
}
int threadCountGuess = tg.activeCount() + 50;
Thread[] threads = new Thread[threadCountGuess];
int threadCountActual = tg.enumerate(threads);
while (threadCountActual == threadCountGuess)
{
threadCountGuess *= 2;
threads = new Thread[threadCountGuess];
threadCountActual = tg.enumerate(threads);
}
return threads;
}
private void clearReferencesRmiTargets()
{
try
{
Class> objectTargetClass = Class.forName("sun.rmi.transport.Target");
Field cclField = objectTargetClass.getDeclaredField("ccl");
cclField.setAccessible(true);
Class> objectTableClass = Class.forName("sun.rmi.transport.ObjectTable");
Field objTableField = objectTableClass.getDeclaredField("objTable");
objTableField.setAccessible(true);
Object objTable = objTableField.get(null);
if (objTable == null) {
return;
}
if ((objTable instanceof Map))
{
Iterator> iter = ((Map)objTable).values().iterator();
while (iter.hasNext())
{
Object obj = iter.next();
Object cclObject = cclField.get(obj);
if (this == cclObject) {
iter.remove();
}
}
}
Field implTableField = objectTableClass.getDeclaredField("implTable");
implTableField.setAccessible(true);
Object implTable = implTableField.get(null);
if (implTable == null) {
return;
}
if ((implTable instanceof Map))
{
Iterator> iter = ((Map)implTable).values().iterator();
while (iter.hasNext())
{
Object obj = iter.next();
Object cclObject = cclField.get(obj);
if (this == cclObject) {
iter.remove();
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void clearReferencesResourceBundles()
{
try
{
Field cacheListField = ResourceBundle.class.getDeclaredField("cacheList");
cacheListField.setAccessible(true);
Map, ?> cacheList = (Map)cacheListField.get(null);
Set> keys = cacheList.keySet();
Field loaderRefField = null;
Iterator> keysIter = keys.iterator();
while (keysIter.hasNext())
{
Object key = keysIter.next();
if (loaderRefField == null)
{
loaderRefField = key.getClass().getDeclaredField("loaderRef");
loaderRefField.setAccessible(true);
}
WeakReference> loaderRef = (WeakReference)loaderRefField.get(key);
ClassLoader loader = (ClassLoader)loaderRef.get();
while ((loader != null) && (loader != this.loader)) {
loader = loader.getParent();
}
if (loader != null) {
keysIter.remove();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}