{"id":40395132,"url":"https://github.com/evosec/tomcat-classloader-leak-test","last_synced_at":"2026-01-20T13:03:46.783Z","repository":{"id":57744204,"uuid":"80124384","full_name":"evosec/tomcat-classloader-leak-test","owner":"evosec","description":"An integration test for your webapp that checks if it cleans up after itself.","archived":false,"fork":false,"pushed_at":"2018-12-11T14:16:53.000Z","size":16638,"stargazers_count":3,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-07-15T16:48:01.697Z","etag":null,"topics":["classloader","integration","java","leak","memory","metaspace","permgen","test","tomcat","webapp"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evosec.png","metadata":{"files":{"readme":"README.markdown","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.markdown","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-26T15:00:38.000Z","updated_at":"2021-09-02T03:03:33.000Z","dependencies_parsed_at":"2022-08-30T10:51:34.883Z","dependency_job_id":null,"html_url":"https://github.com/evosec/tomcat-classloader-leak-test","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/evosec/tomcat-classloader-leak-test","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evosec%2Ftomcat-classloader-leak-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evosec%2Ftomcat-classloader-leak-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evosec%2Ftomcat-classloader-leak-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evosec%2Ftomcat-classloader-leak-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evosec","download_url":"https://codeload.github.com/evosec/tomcat-classloader-leak-test/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evosec%2Ftomcat-classloader-leak-test/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28603411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T12:01:53.233Z","status":"ssl_error","status_checked_at":"2026-01-20T12:01:46.545Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["classloader","integration","java","leak","memory","metaspace","permgen","test","tomcat","webapp"],"created_at":"2026-01-20T13:03:46.713Z","updated_at":"2026-01-20T13:03:46.773Z","avatar_url":"https://github.com/evosec.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tomcat-classloader-leak-test\r\n\r\n[![Build Status](https://travis-ci.org/evosec/tomcat-classloader-leak-test.svg?branch=develop)](https://travis-ci.org/evosec/tomcat-classloader-leak-test)\r\n\r\nAn integration test for your webapp that checks if it cleans up after itself.\r\n\r\n## Usage\r\n\r\n`pom.xml`:\r\n~~~\r\n\u003cdependency\u003e\r\n    \u003cgroupId\u003ede.evosec\u003c/groupId\u003e\r\n    \u003cartifactId\u003etomcat-classloader-leak-test\u003c/artifactId\u003e\r\n    \u003cversion\u003e0.0.1\u003c/version\u003e\r\n    \u003cscope\u003etest\u003c/scope\u003e\r\n\u003c/dependency\u003e\r\n\r\n\u003cplugin\u003e\r\n    \u003cgroupId\u003eorg.codehaus.mojo\u003c/groupId\u003e\r\n    \u003cartifactId\u003ebuild-helper-maven-plugin\u003c/artifactId\u003e\r\n    \u003cexecutions\u003e\r\n        \u003cexecution\u003e\r\n            \u003cid\u003eadd-test-source\u003c/id\u003e\r\n            \u003cphase\u003egenerate-test-sources\u003c/phase\u003e\r\n            \u003cgoals\u003e\r\n                \u003cgoal\u003eadd-test-source\u003c/goal\u003e\r\n            \u003c/goals\u003e\r\n            \u003cconfiguration\u003e\r\n                \u003csources\u003e\r\n                    \u003csource\u003esrc/it/java\u003c/source\u003e\r\n                \u003c/sources\u003e\r\n            \u003c/configuration\u003e\r\n        \u003c/execution\u003e\r\n    \u003c/executions\u003e\r\n\u003c/plugin\u003e\r\n\r\n\u003cplugin\u003e\r\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\r\n    \u003cartifactId\u003emaven-failsafe-plugin\u003c/artifactId\u003e\r\n    \u003cexecutions\u003e\r\n        \u003cexecution\u003e\r\n            \u003cgoals\u003e\r\n                \u003cgoal\u003eintegration-test\u003c/goal\u003e\r\n                \u003cgoal\u003everify\u003c/goal\u003e\r\n            \u003c/goals\u003e\r\n            \u003cconfiguration\u003e\r\n                \u003cclasspathDependencyExcludes\u003e\r\n                    \u003cclasspathDependencyExclude\u003eorg.springframework.boot:spring-boot-devtools\u003c/classpathDependencyExclude\u003e\r\n                \u003c/classpathDependencyExcludes\u003e\r\n                \u003cargLine\u003e\u003c![CDATA[-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${project.build.directory} -XX:MaxMetaspaceSize=160m]]\u003e\u003c/argLine\u003e\r\n                \u003ctestSourceDirectory\u003e${project.basedir}/src/it/java\u003c/testSourceDirectory\u003e\r\n                \u003csystemPropertyVariables\u003e\r\n                    \u003cwarName\u003e${project.build.finalName}\u003c/warName\u003e\r\n                \u003c/systemPropertyVariables\u003e\r\n            \u003c/configuration\u003e\r\n        \u003c/execution\u003e\r\n    \u003c/executions\u003e\r\n\u003c/plugin\u003e\r\n~~~\r\n\r\n`src/it/java/com/example/ClassLoaderLeakTestIT`:\r\n~~~\r\npackage com.example;\r\n\r\nimport java.nio.file.Paths;\r\nimport org.junit.Test;\r\nimport de.evosec.leaktest.WebAppTest;\r\n\r\npublic class ClassLoaderLeakTestIT {\r\n\r\n    @Test\r\n    public void test() throws Exception {\r\n        String warName = System.getProperty(\"warName\", \"demo-0.0.1-SNAPSHOT\");\r\n        Path warPath = Paths.get(\"./target/\" + warName + \".war\");\r\n        new WebAppTest().warPath(warPath).contextParameter(\"spring.profiles.active\", \"integration\").run();\r\n    }\r\n\r\n}\r\n~~~\r\n\r\n## How it works\r\n\r\n1. The test setups an embedded Tomcat.\r\n2. Then the war file from the build is added to the Tomcat\r\n3. Wait for the application to start (By default it waits until the root returns HTTP 200 OK)\r\n4. Get a WeakReference to the started Context\r\n5. Stop the application\r\n6. Start creating classes to put the Metaspace/PermGen under pressure - thus triggering GC eventually.\r\n7. Stop when WeakReference is null - thus the Context has been cleaned up properly. If not, then there is a ClassLoader leak.\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevosec%2Ftomcat-classloader-leak-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevosec%2Ftomcat-classloader-leak-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevosec%2Ftomcat-classloader-leak-test/lists"}