/** * Attempt to identify the contexts that have a class loader memory leak. * This is usually triggered on context reload. Note: This method attempts * to force a full garbage collection. This should be used with extreme * caution on a production system. */ public String[] findReloadedContextMemoryLeaks() { System.gc(); List<String> result = new ArrayList<String>(); for (Map.Entry<ClassLoader, String> entry : childClassLoaders.entrySet()) { ClassLoader cl = entry.getKey(); if (cl instanceof WebappClassLoaderBase) { if (!((WebappClassLoaderBase) cl).isStarted()) { result.add(entry.getValue()); } } } return result.toArray(new String[result.size()]); }
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain"); PrintWriter out = resp.getWriter(); ClassLoader system = ClassLoader.getSystemClassLoader(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); while (cl != null) { if (system == cl) { out.print("SYSTEM,"); } else if (custom == cl) { out.print("CUSTOM,"); } else if (cl instanceof WebappClassLoaderBase) { out.print("WEBAPP,"); } else { out.print("OTHER,"); } cl = cl.getParent(); } }
private void checkForRequestThreads(WebappLoader webappLoader) throws Exception { Method getThreadsMethod = WebappClassLoaderBase.class.getDeclaredMethod("getThreads"); getThreadsMethod.setAccessible(true); Method isRequestThreadMethod = WebappClassLoaderBase.class.getDeclaredMethod("isRequestThread", Thread.class); isRequestThreadMethod.setAccessible(true); ClassLoader webappClassLoader = webappLoader.getClassLoader(); Thread[] threads = (Thread[]) getThreadsMethod.invoke(webappClassLoader); for (Thread thread : threads) { if (thread == null) { continue; } if ((boolean) isRequestThreadMethod.invoke(webappClassLoader, thread)) { StringBuilder sb = new StringBuilder(); for (StackTraceElement element : thread.getStackTrace()) { sb.append(element); sb.append('\n'); } logger.error("tomcat request thread \"{}\" is still active:\n{}", thread.getName(), sb); } } }
private void checkForRequestThreads(WebappLoader webappLoader) throws Exception { Method getThreadsMethod = WebappClassLoaderBase.class.getDeclaredMethod("getThreads"); getThreadsMethod.setAccessible(true); Method isRequestThreadMethod = WebappClassLoaderBase.class.getDeclaredMethod("isRequestThread", Thread.class); isRequestThreadMethod.setAccessible(true); ClassLoader webappClassLoader = webappLoader.getClassLoader(); Thread[] threads = (Thread[]) getThreadsMethod.invoke(webappClassLoader); for (Thread thread : threads) { if (thread == null) { continue; } if ((Boolean) isRequestThreadMethod.invoke(webappClassLoader, thread)) { StringBuilder sb = new StringBuilder(); for (StackTraceElement element : thread.getStackTrace()) { sb.append(element); sb.append('\n'); } logger.error("tomcat request thread \"{}\" is still active:\n{}", thread.getName(), sb); } } }