JavaSpring应用程序存在内存泄漏。系统非堆内存不断增加

JavaSpring应用程序存在内存泄漏。系统非堆内存不断增加,java,spring,memory-leaks,Java,Spring,Memory Leaks,我已使用yourkit profiler监视我的Web应用程序。保留最大大小的主要对象是SessionFactoryImpl、webappclassloader和CGlib对象。 *spring crone调度程序是否导致内存泄漏? 我尝试过的解决方案 1) 我试图杀死线程,但他们仍然活着 2) 关闭所有连接 3) 将null分配给我在代码中使用的所有变量和对象 4) 我还申请了服务器端 -Xms128m -Xmx256m -XX:MaxPermSize=512m -XX:+UseConcMar

我已使用yourkit profiler监视我的Web应用程序。保留最大大小的主要对象是SessionFactoryImpl、webappclassloader和CGlib对象。 *spring crone调度程序是否导致内存泄漏? 我尝试过的解决方案

1) 我试图杀死线程,但他们仍然活着

2) 关闭所有连接

3) 将null分配给我在代码中使用的所有变量和对象

4) 我还申请了服务器端

-Xms128m -Xmx256m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+HeapDumpOnOutOfMemoryError -XX:MaxHeapFreeRatio=70 -XX:ReservedCodeCacheSize=32m -XX:+UseCodeCacheFlushing -XX:-OmitStackTraceInFastThrow
5) 我在web.xml中添加了防漏库

<listener>
    <listener-class>se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventorListener
        </listener-class>
  </listener>
  <context-param>
    <param-name>ClassLoaderLeakPreventor.stopThreads</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>ClassLoaderLeakPreventor.stopTimerThreads</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>ClassLoaderLeakPreventor.executeShutdownHooks</param-name>
    <param-value>true</param-value>
  </context-param>
  <context-param>
    <param-name>ClassLoaderLeakPreventor.threadWaitMs</param-name>
    <param-value>5000</param-value>
  </context-param>
  <context-param>
    <param-name>ClassLoaderLeakPreventor.shutdownHookWaitMs</param-name>
    <param-value>10000</param-value>
  </context-param>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/root-context.xml</param-value>
  </context-param> 

se.jiderhamn.classloader.leak.prevention.classloader防泄漏器Listener
ClassLoaderLeakPreventor.stopThreads
真的
ClassLoaderLeakPreventor.stopTimerThreads
真的
ClassLoaderLeakPreventor.executeShutdownHooks
真的
ClassLoaderLeakPreventor.threadWaitMs
5000
ClassLoaderLeakPreventor.shutdownHookWaitMs
10000
上下文配置位置
/WEB-INF/root-context.xml
6) 我还添加了ContextFinalizer类

 package com.thl.test;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Enumeration;
import java.util.Set;

import javax.servlet.ServletContextEvent;

import org.apache.commons.logging.LogFactory;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.Proxy;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.web.util.IntrospectorCleanupListener;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;

import se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor;

public class ContextFinalizer extends IntrospectorCleanupListener {

    private ClassLoader loader = null;

    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Calling>>>>>>>>>>>>>>>>>>>>>>>.?");
        /* Introspector.flushCaches(); */
        ClassLoader cl1 = Thread.currentThread().getContextClassLoader();
        CachedIntrospectionResults.clearClassLoader(cl1);
        LogFactory.releaseAll();
        ClassLoaderLeakPreventor.gc();
        try {
            AbandonedConnectionCleanupThread.shutdown();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        /*Enhancer.registerCallbacks(enhanced, null);*/
        // cleanUp();
    }

    @SuppressWarnings("deprecation")
    public void contextDestroyed(ServletContextEvent sce) {
        /*
         * Thread t = Thread.currentThread();
         * Runtime.getRuntime().addShutdownHook(t);
         */
        System.out.println("Good Bye>>>>>>>>>>>>>>>>>>>>>.?");
        cleanUp();
        ClassLoaderLeakPreventor.gc();
        java.beans.Introspector.flushCaches();
        java.security.Security.removeProvider(null);
        ClassLoader cl1 = Thread.currentThread().getContextClassLoader();
        CachedIntrospectionResults.clearClassLoader(cl1);
        LogFactory.releaseAll();
        org.apache.log4j.LogManager.shutdown();

        Enumeration<Driver> drivers = DriverManager.getDrivers();
        Driver d = null;

        ClassLoader cl = Thread.currentThread().getContextClassLoader();

        while (drivers.hasMoreElements()) {
            try {
                d = drivers.nextElement();
                if (d.getClass().getClassLoader() == cl) {
                    DriverManager.deregisterDriver(d);
                } else {
                    DriverManager.deregisterDriver(d);
                }
            } catch (Exception ex) {
                // LOGGER.warn(String.format("Error deregistering driver %s",
                // d), ex);
            }
        }

        /*
         * if (ConnectionImpl.class.getClassLoader() ==
         * getClass().getClassLoader()) { Field f = null; try { f =
         * ConnectionImpl.class.getDeclaredField("cancelTimer");
         * f.setAccessible(true); Timer timer = (Timer) f.get(null);
         * timer.cancel(); }catch(Exception e) {
         * 
         * }finally { f = null; } }
         */

        try {
            com.mysql.jdbc.AbandonedConnectionCleanupThread.shutdown();

        } catch (InterruptedException e) {
        } finally {
            try {

                /* org.apache.commons.pool.impl.GenericObjectPool. */

                com.mysql.jdbc.AbandonedConnectionCleanupThread.shutdown();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);
        for (Thread t : threadArray) {
            /*
             * if (t.isInterrupted()) { break; }
             */

            if (t.getName().contains("Abandoned connection cleanup thread")) {
                synchronized (t) {
                    // don't complain, it works
                    if (t.isAlive()) {
                        System.out.println("Alive True");
                        if (t.isDaemon()) {
                            System.out.println("isDaemon True");
                            t.stop();
                        } else {
                            System.out.println("isDaemon False");
                            t.stop();
                        }
                    } else {
                        System.out.println("Alive Flase");
                        t.stop();
                    }
                    // new Timer(true);
                }
            } else if (t.getName().contains("http-nio-8081-exec-1")) {
                System.out.println("http-nio-8081-exec-1>>>>>>>>>>>");
            } else {
                System.out.println("Else If Block");
                synchronized (t) {
                    t.setDaemon(true);
                    t.suspend();
                }
            }
        }
        java.beans.Introspector.flushCaches();

    }

    public void onApplicationEvent(ContextRefreshedEvent arg0) {
        System.out.println("--------------- Context Refreshed -----------------");
        System.out.println("::::::::::::::::::::::::  Calling   :::::::::::::::::::::::::::::");

        ApplicationContext context = arg0.getApplicationContext();
        System.out.println(context.getDisplayName());
    }

    private void cleanUp() {
        Thread[] threads = getThreads();
        for (Thread thread : threads) {
            if (thread != null) {
                System.out.println("Inside IFF");
                cleanContextClassLoader(thread);
                cleanOrb(thread);
                cleanThreadLocal(thread);

            }

        }
    }

    private Thread[] getThreads() {
        ThreadGroup rootGroup = Thread.currentThread().getThreadGroup();
        ThreadGroup parentGroup;
        if (rootGroup.getParent() != null) {
            parentGroup = rootGroup.getParent();
            if (parentGroup != null) {
                rootGroup = parentGroup;
            }
        }
        Thread[] threads = new Thread[rootGroup.activeCount()];
        while (rootGroup.enumerate(threads, true) == threads.length) {
            threads = new Thread[threads.length * 2];
        }
        return threads;
    }

    private boolean loaderRemovable(ClassLoader cl) {
        if (cl == null) {
            return false;
        }
        Object isDoneCalled = getObject(cl, "doneCalled");
        String clName = cl.getClass().getName();
        loader = Thread.currentThread().getContextClassLoader();
        String ldr = null;
        loader = loader.getParent();
        if (loader != null) {
            // loader.getParent();
            ldr = loader.getClass().getName();
        }

        if (clName != null && ldr != null && isDoneCalled != null) {
            if (clName.equalsIgnoreCase(ldr) && isDoneCalled instanceof Boolean && (Boolean) isDoneCalled) {
                return true;
            }
        }

        return loader == cl;
    }

    private Field getField(Class clazz, String fieldName) {
        Field f = null;
        try {
            f = clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException ex) {

        } catch (SecurityException ex) {
        }

        if (f == null) {
            Class parent = clazz.getSuperclass();
            if (parent != null) {
                f = getField(parent, fieldName);
            }
        }
        if (f != null) {
            f.setAccessible(true);
        }
        return f;
    }

    private Object getObject(Object instance, String fieldName) {
        Class clazz = instance.getClass();
        Field f = getField(clazz, fieldName);
        if (f != null) {
            try {
                return f.get(instance);
            } catch (IllegalArgumentException | IllegalAccessException ex) {
            }
        }
        return null;
    }

    private void cleanContextClassLoader(Thread thread) {
        if (loaderRemovable(thread.getContextClassLoader())) {
            thread.setContextClassLoader(null);
        }
    }

    private void cleanOrb(Thread thread) {
        Object currentWork = getObject(thread, "currentWork");
        if (currentWork != null) {
            Object orb = getObject(currentWork, "orb");
            if (orb != null) {
                Object transportManager = getObject(orb, "transportManager");
                if (transportManager != null) {
                    Thread selector = (Thread) getObject(transportManager, "selector");
                    if (selector != null && loaderRemovable(selector.getContextClassLoader())) {
                        selector.setContextClassLoader(null);
                    }
                }
            }
        }
    }

    private void removeThreadLocal(Object entry, Object threadLocals, Thread thread) {
        ThreadLocal threadLocal = (ThreadLocal) getObject(entry, "referent");
        if (threadLocal != null) {
            Class clazz = null;
            try {
                clazz = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
            } catch (ClassNotFoundException ex) {
            }
            if (clazz != null) {
                Method removeMethod = null;
                Method[] methods = clazz.getDeclaredMethods();
                if (methods != null) {
                    for (Method method : methods) {
                        if (method.getName().equals("remove")) {
                            removeMethod = method;
                            removeMethod.setAccessible(true);
                            break;
                        }
                    }
                }
                if (removeMethod != null) {
                    try {
                        removeMethod.invoke(threadLocals, threadLocal);
                    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                    }
                }

            }

        }
    }

    private void cleanThreadLocal(Thread thread) {
        Object threadLocals = getObject(thread, "threadLocals");
        if (threadLocals != null) {
            Object table = getObject(threadLocals, "table");
            if (table != null) {
                int size = Array.getLength(table);
                for (int i = 0; i < size; i++) {
                    Object entry = Array.get(table, i);
                    if (entry != null) {
                        Field valueField = getField(entry.getClass(), "value");
                        if (valueField != null) {
                            try {
                                Object value = valueField.get(entry);
                                if (value != null && value instanceof ClassLoader
                                        && loaderRemovable((ClassLoader) value)) {
                                    removeThreadLocal(entry, threadLocals, thread);
                                }
                            } catch (IllegalArgumentException | IllegalAccessException ex) {

                            }

                        }
                    }

                }
            }
        }
    }

}
package com.thl.test;
导入java.lang.reflect.Array;
导入java.lang.reflect.Field;
导入java.lang.reflect.InvocationTargetException;
导入java.lang.reflect.Method;
导入java.sql.Driver;
导入java.sql.DriverManager;
导入java.util.Enumeration;
导入java.util.Set;
导入javax.servlet.ServletContextEvent;
导入org.apache.commons.logging.LogFactory;
导入org.springframework.beans.CachedIntrospectionResults;
导入org.springframework.cglib.proxy.Enhancer;
导入org.springframework.cglib.proxy.proxy;
导入org.springframework.context.ApplicationContext;
导入org.springframework.context.event.ContextRefreshedEvent;
导入org.springframework.web.util.introspectorcleanupliner;
导入com.mysql.jdbc.弃用连接CleanupThread;
导入se.jiderhamn.classloader.leak.prevention.ClassLoaderLeakPreventor;
公共类ContextFinalizer扩展了内省库提升库{
私有类加载器=null;
public void contextInitialized(ServletContextEvent sce){
System.out.println(“调用>>>>>>>>>>>>>>>.?”;
/*内省者。flushCaches()*/
ClassLoader cl1=Thread.currentThread().getContextClassLoader();
clearClassLoader(cl1);
LogFactory.releaseAll();
ClassLoaderLeakPreventor.gc();
试一试{
放弃连接CleanupThread.shutdown();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
/*Enhancer.registerCallbacks(增强型,空)*/
//清理();
}
@抑制警告(“弃用”)
公共无效上下文已销毁(ServletContextEvent sce){
/*
*Thread t=Thread.currentThread();
*Runtime.getRuntime().addShutdownHook(t);
*/
System.out.println(“再见”>>>>>>>>>>>>>.?”;
清理();
ClassLoaderLeakPreventor.gc();
java.beans.Introspector.flushCaches();
java.security.security.removeProvider(null);
ClassLoader cl1=Thread.currentThread().getContextClassLoader();
clearClassLoader(cl1);
LogFactory.releaseAll();
org.apache.log4j.LogManager.shutdown();
枚举驱动程序=DriverManager.getDrivers();
驱动程序d=null;
ClassLoader cl=Thread.currentThread().getContextClassLoader();
while(drivers.hasMoreElements()){
试一试{
d=drivers.nextElement();
if(d.getClass().getClassLoader()==cl){
DriverManager.deregisterDriver(d);
}否则{
DriverManager.deregisterDriver(d);
}
}捕获(例外情况除外){
//LOGGER.warn(String.format(“注销驱动程序%s时出错”),
//(d)ex);
}
}
/*
*if(ConnectionImpl.class.getClassLoader()==
*getClass().getClassLoader(){Field f=null;请尝试{f=
*ConnectionImpl.class.getDeclaredField(“cancelTimer”);
*f.setAccessible(true);Timer=(Timer)f.get(null);
*timer.cancel();}catch(异常e){
* 
*}最后{f=null;}}
*/
试一试{
com.mysql.jdbc.废弃连接CleanupThread.shutdown();
}捕捉(中断异常e){
}最后{
试一试{
/*org.apache.commons.pool.impl.GenericObject池*/
com.mysql.jdbc.废弃连接CleanupThread.shutdown();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
Set threadSet=Thread.getAllStackTraces().keySet();
Thread[]threadArray=threadSet.toArray(新线程[threadSet.size()]);
for(线程t:threadArray){
/*
*如果(t.isInterrupted()){break;}
*/
if(t.getName().contains(“放弃的连接清理线程”)){
同步(t){
//别抱怨,这很管用
if(t.isAlive()){
System.out.println(“真实有效”);
if(t.isDaemon()){
System.out.println(“isDaemon True”);
t、 停止();
}否则{
System.out.println(“isDaemon False”);
t、 停止();
}
}否则{
System.out.println(“活动Flase”);
t、 停止();
}
//新定时器(真);
}
}else if(t.getName()包含(“http-nio-8081-exec-1”)){
System.out.prin