ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/test/org/apache/catalina/loader/TesterWebappClassLoaderThreadLocalMemoryLeak.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/test/org/apache/catalina/loader/TesterWebappClassLoaderThreadLocalMemoryLeak.java
Status
scanned
Type
file
Name
TesterWebappClassLoaderThreadLocalMemoryLeak.java
Extension
.java
Programming language
Java
Mime type
text/plain
File type
ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
8243 (8.0 KB)
MD5
f9d6f1526aac26614f61078183dea2be
SHA1
641871a24c66d26168aea025cf8994535822e0b4
SHA256
61b9d01d91dfb8c64a2240673c4d318210e58f6371d5f7045dbd166637076481
SHA512

      
    
SHA1_git
88df1137489f0a15da5bdee5f25c51754eccebd9
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
TesterWebappClassLoaderThreadLocalMemoryLeak.java | 8.0 KB |

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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.apache.catalina.loader; import java.io.InputStream; import java.util.concurrent.Executor; import jakarta.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Test; import org.apache.catalina.Context; import org.apache.catalina.core.JreMemoryLeakPreventionListener; import org.apache.catalina.core.StandardHost; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; import org.apache.tomcat.unittest.TesterLogValidationFilter; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.threads.ThreadPoolExecutor; /* * These unit tests are ignored by default as they are not reliable. They have * been failing regularly on Gump for some time and have recently started to * fail regularly on markt's laptop. * * The problem is that the ThreadLocal Maps are affected by GC. If GC occurs at * the wrong point, the leaking ThreadLocal will be cleaned up and the test will * fail. It is not possible to force the test to pass without effectively * changing the nature of the test so it no longer tests detection of leaks via * ThreadLocals. * * The test has been left in place since it will work reasonably reliably on * most systems (just not all and particularly some of the ASF's CI systems) and * still may be useful if a bug is reported in this area in the future. */ public class TesterWebappClassLoaderThreadLocalMemoryLeak extends TomcatBaseTest { @Test public void testThreadLocalLeak1() throws Exception { Tomcat tomcat = getTomcatInstance(); // Need to make sure we see a leak for the right reasons tomcat.getServer().addLifecycleListener(new JreMemoryLeakPreventionListener()); // No file system docBase required Context ctx = getProgrammaticRootContext(); Tomcat.addServlet(ctx, "leakServlet1", "org.apache.tomcat.unittest.TesterLeakingServlet1"); ctx.addServletMappingDecoded("/leak1", "leakServlet1"); tomcat.start(); Executor executor = tomcat.getConnector().getProtocolHandler().getExecutor(); ((ThreadPoolExecutor) executor).setThreadRenewalDelay(-1); // Configure logging filter to check leak message appears TesterLogValidationFilter f = TesterLogValidationFilter.add(null, "The web application [ROOT] created a ThreadLocal with key of", null, "org.apache.catalina.loader.WebappClassLoaderBase"); // Need to force loading of all web application classes via the web // application class loader loadClass("TesterCounter", (WebappClassLoaderBase) ctx.getLoader().getClassLoader()); loadClass("TesterLeakingServlet1", (WebappClassLoaderBase) ctx.getLoader().getClassLoader()); // This will trigger the ThreadLocal creation int rc = getUrl("http://localhost:" + getPort() + "/leak1", new ByteChunk(), null); // Make sure request is OK Assert.assertEquals(HttpServletResponse.SC_OK, rc); // Destroy the context ctx.stop(); tomcat.getHost().removeChild(ctx); ctx = null; // Make sure we have a memory leak String[] leaks = ((StandardHost) tomcat.getHost()).findReloadedContextMemoryLeaks(); Assert.assertNotNull(leaks); Assert.assertTrue(leaks.length > 0); // Make sure the message was logged Assert.assertEquals(1, f.getMessageCount()); } @Test public void testThreadLocalLeak2() throws Exception { Tomcat tomcat = getTomcatInstance(); // Need to make sure we see a leak for the right reasons tomcat.getServer().addLifecycleListener(new JreMemoryLeakPreventionListener()); // No file system docBase required Context ctx = getProgrammaticRootContext(); Tomcat.addServlet(ctx, "leakServlet2", "org.apache.tomcat.unittest.TesterLeakingServlet2"); ctx.addServletMappingDecoded("/leak2", "leakServlet2"); tomcat.start(); Executor executor = tomcat.getConnector().getProtocolHandler().getExecutor(); ((ThreadPoolExecutor) executor).setThreadRenewalDelay(-1); // Configure logging filter to check leak message appears TesterLogValidationFilter f = TesterLogValidationFilter.add(null, "The web application [ROOT] created a ThreadLocal with key of", null, "org.apache.catalina.loader.WebappClassLoaderBase"); // Need to force loading of all web application classes via the web // application class loader loadClass("TesterCounter", (WebappClassLoaderBase) ctx.getLoader().getClassLoader()); loadClass("TesterThreadScopedHolder", (WebappClassLoaderBase) ctx.getLoader().getClassLoader()); loadClass("TesterLeakingServlet2", (WebappClassLoaderBase) ctx.getLoader().getClassLoader()); // This will trigger the ThreadLocal creation int rc = getUrl("http://localhost:" + getPort() + "/leak2", new ByteChunk(), null); // Make sure request is OK Assert.assertEquals(HttpServletResponse.SC_OK, rc); // Destroy the context ctx.stop(); tomcat.getHost().removeChild(ctx); ctx = null; // Make sure we have a memory leak String[] leaks = ((StandardHost) tomcat.getHost()).findReloadedContextMemoryLeaks(); Assert.assertNotNull(leaks); Assert.assertTrue(leaks.length > 0); // Make sure the message was logged Assert.assertEquals(1, f.getMessageCount()); } /** * Utility method to ensure that classes are loaded by the WebappClassLoader. We can't just create classes since * they will be loaded by the current class loader rather than the WebappClassLoader. This would mean that no leak * occurred making the test for a leak rather pointless So, we load the bytes via the current class loader but * define the class with the WebappClassLoader. This method assumes that all classes are in the current package. */ private void loadClass(String name, WebappClassLoaderBase cl) throws Exception { try (InputStream is = cl.getResourceAsStream("org/apache/tomcat/unittest/" + name + ".class")) { // We know roughly how big the class will be (~ 1K) so allow 2k as a // starting point byte[] classBytes = new byte[2048]; int offset = 0; int read = is.read(classBytes, offset, classBytes.length - offset); while (read > -1) { offset += read; if (offset == classBytes.length) { // Buffer full - double size byte[] tmp = new byte[classBytes.length * 2]; System.arraycopy(classBytes, 0, tmp, 0, classBytes.length); classBytes = tmp; } read = is.read(classBytes, offset, classBytes.length - offset); } Class<?> lpClass = cl.doDefineClass("org.apache.tomcat.unittest." + name, classBytes, 0, offset, cl.getClass().getProtectionDomain()); // Make sure we can create an instance lpClass.getConstructor().newInstance(); } } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
13.46
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9