/* * #%L * carewebframework * %% * Copyright (C) 2008 - 2016 Regenstrief Institute, Inc. * %% * Licensed 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. * * This Source Code Form is also subject to the terms of the Health-Related * Additional Disclaimer of Warranty and Limitation of Liability available at * * http://www.carewebframework.org/licensing/disclaimer. * * #L% */ package org.carewebframework.ui.util; import java.lang.reflect.Field; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * */ public final class MemoryLeakPreventionUtil { private static final Log log = LogFactory.getLog(MemoryLeakPreventionUtil.class); /** * Attempt all known cleanup measures. * * @see #clearReferencesHttpClientKeepAliveThread() */ /*@see #shutdownLogging()*/ public static void clean() { log.info("Attempting to prevent known memory leaks"); clearReferencesHttpClientKeepAliveThread(); /*TODO Create some type of registry so that there is no dependency to the logging extension module. shutdownLogging();*/ } /** * @see LogUtil#shutdown() */ /* public static void shutdownLogging() { LogUtil.shutdown(); }*/ /** * CWI-1409 * <p> * This does what Tomcat 7 context attribute clearReferencesHttpClientKeepAliveThread is * suggested to do but doesn't. Using reflection in this manner is a last resort. * <ul> * <li>JDK 7 is said to fix the keepAliveTimer thread bug.</li> * <li>Tomcat 7.0.x context attribute clearReferencesHttpClientKeepAliveThread is suggested to * fix this leak but does not</li> * </ul> */ @SuppressWarnings("restriction") protected static void clearReferencesHttpClientKeepAliveThread() { try { Field kac = sun.net.www.http.HttpClient.class.getDeclaredField("kac"); kac.setAccessible(true); Field keepAliveTimer = sun.net.www.http.KeepAliveCache.class.getDeclaredField("keepAliveTimer"); keepAliveTimer.setAccessible(true); Thread t = (Thread) keepAliveTimer.get(kac.get(null));//kac is a static field, hence null argument if (t != null) {//May not actually be running log.debug("KeepAliveTimer contextClassLoader: " + t.getContextClassLoader()); if (t.getContextClassLoader() == Thread.currentThread().getContextClassLoader()) { t.setContextClassLoader(ClassLoader.getSystemClassLoader()); log.info("Changed KeepAliveTimer classloader to system to prevent leak."); } } } catch (Exception e) { log.warn( "Exception occurred attempting to prevent sun.net.www.http.HttpClient keepAliveTimer memory leak. Note: this code should not be necessary w/ java7", e); } } }