Skip to content

Commit da759fb

Browse files
Flossyclaude
andcommitted
Add CI/CD security scanning and memory leak documentation
Issue #23 - Add CI/CD Security Scanning: - Add CodeQL security scanning workflow (.github/workflows/codeql.yml) - Runs on push to main, pull requests, and weekly schedule - Uses security-extended and security-and-quality queries - Analyzes Java code for security vulnerabilities - Add OWASP Dependency-Check to main workflow - Scans dependencies for known CVEs - Fails build on CVSS score >= 7 (high/critical) - Uploads dependency check report as artifact - Set to continue-on-error to not block deployments initially Issue #27 - Add Memory Leak Documentation: - Comprehensive memory leak prevention documentation in JClassLoader javadoc - Hot reload best practices with code examples - Memory leak detection techniques - Common memory leak causes (ThreadLocal, static caches, thread pools) - Proper cleanup examples (try-with-resources, null references, close()) - Examples showing correct vs incorrect hot reload patterns Benefits: - Automated security vulnerability detection - Dependency vulnerability scanning - Users educated on memory leak prevention - Clear hot reload implementation guidance Fixes #23, #27 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent ce6ecf9 commit da759fb

3 files changed

Lines changed: 131 additions & 7 deletions

File tree

.github/workflows/codeql.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: "CodeQL Security Scanning"
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
schedule:
9+
# Run at 2:30 AM every Monday
10+
- cron: '30 2 * * 1'
11+
12+
jobs:
13+
analyze:
14+
name: Analyze Code Security
15+
runs-on: ubuntu-latest
16+
permissions:
17+
actions: read
18+
contents: read
19+
security-events: write
20+
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
language: [ 'java' ]
25+
26+
steps:
27+
- name: Checkout repository
28+
uses: actions/checkout@v4
29+
30+
- name: Setup JDK 21
31+
uses: actions/setup-java@v4
32+
with:
33+
distribution: 'temurin'
34+
java-version: '21'
35+
36+
# Initialize CodeQL
37+
- name: Initialize CodeQL
38+
uses: github/codeql-action/init@v3
39+
with:
40+
languages: ${{ matrix.language }}
41+
queries: security-extended,security-and-quality
42+
43+
# Build the project
44+
- name: Build with Maven
45+
run: mvn clean compile -DskipTests
46+
47+
# Perform CodeQL Analysis
48+
- name: Perform CodeQL Analysis
49+
uses: github/codeql-action/analyze@v3
50+
with:
51+
category: "/language:${{matrix.language}}"

.github/workflows/main.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ jobs:
6161
- name: Building
6262
run: "mvn -U clean install"
6363

64+
- name: OWASP Dependency Check
65+
run: "mvn org.owasp:dependency-check-maven:check -DfailBuildOnCVSS=7"
66+
continue-on-error: true
67+
68+
- name: Upload Dependency Check Report
69+
if: always()
70+
uses: actions/upload-artifact@v4
71+
with:
72+
name: dependency-check-report
73+
path: target/dependency-check-report.html
74+
retention-days: 30
75+
6476
- name: Deploy to packagecloud.io
6577
run: "mvn -DskipTests deploy"
6678

src/main/java/org/flossware/jclassloader/JClassLoader.java

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,74 @@
1717
* Custom ClassLoader supporting multiple class sources with caching and lifecycle management.
1818
* Implements AutoCloseable for proper resource cleanup and memory leak prevention.
1919
*
20-
* IMPORTANT: Always close this ClassLoader when done to prevent memory leaks,
21-
* especially in hot reload scenarios. Use try-with-resources:
22-
* <pre>
23-
* try (JClassLoader loader = JClassLoader.builder()...build()) {
24-
* // Use loader
25-
* } // Automatically closed
26-
* </pre>
20+
* <h2>Memory Leak Prevention</h2>
21+
* <p><b>CRITICAL:</b> ClassLoaders can cause memory leaks if not properly managed. This ClassLoader
22+
* holds strong references to all loaded classes, which prevents those classes (and their static fields)
23+
* from being garbage collected until the ClassLoader itself is collected.</p>
24+
*
25+
* <h3>Always Close When Done</h3>
26+
* <p>Use try-with-resources to ensure proper cleanup:</p>
27+
* <pre>{@code
28+
* try (JClassLoader loader = JClassLoader.builder()
29+
* .addLocalSource("/path/to/classes")
30+
* .build()) {
31+
* Class<?> clazz = loader.loadClass("com.example.MyClass");
32+
* // Use the class
33+
* } // Automatically closes and releases resources
34+
* }</pre>
35+
*
36+
* <h3>Hot Reload / Class Reloading Scenarios</h3>
37+
* <p>When implementing hot reload or dynamic class reloading:</p>
38+
* <ol>
39+
* <li><b>Create a new ClassLoader for each reload</b> - Don't reuse ClassLoaders</li>
40+
* <li><b>Close the old ClassLoader</b> - Call {@link #close()} on the old loader</li>
41+
* <li><b>Clear all references</b> - Null out references to classes from the old loader</li>
42+
* <li><b>Avoid static state</b> - Static fields in loaded classes prevent GC</li>
43+
* <li><b>Be careful with ThreadLocal</b> - Can leak ClassLoader references</li>
44+
* </ol>
45+
*
46+
* <p><b>Example - Proper Hot Reload:</b></p>
47+
* <pre>{@code
48+
* // Old way (MEMORY LEAK - old ClassLoader never released):
49+
* JClassLoader loader = JClassLoader.builder()...build();
50+
* // ... use loader ...
51+
* loader = JClassLoader.builder()...build(); // OLD LOADER LEAKED!
52+
*
53+
* // Correct way:
54+
* JClassLoader oldLoader = currentLoader;
55+
* JClassLoader newLoader = JClassLoader.builder()...build();
56+
*
57+
* // Switch to new loader
58+
* currentLoader = newLoader;
59+
*
60+
* // Release old loader and all its classes
61+
* if (oldLoader != null) {
62+
* oldLoader.close(); // Close resources
63+
* oldLoader = null; // Clear reference
64+
* }
65+
* System.gc(); // Suggest GC (doesn't guarantee collection)
66+
* }</pre>
67+
*
68+
* <h3>Memory Leak Detection</h3>
69+
* <p>To detect ClassLoader leaks in your application:</p>
70+
* <ul>
71+
* <li>Use heap dumps and memory profilers (VisualVM, YourKit, JProfiler)</li>
72+
* <li>Look for multiple instances of the same ClassLoader class</li>
73+
* <li>Check for references from Thread contexts, static fields, or caches</li>
74+
* <li>Monitor {@link #isClosed()} - closed loaders should be GC'd</li>
75+
* </ul>
76+
*
77+
* <h3>Common Memory Leak Causes</h3>
78+
* <ul>
79+
* <li><b>ThreadLocal variables</b> holding class references</li>
80+
* <li><b>Static caches</b> holding instances from dynamically loaded classes</li>
81+
* <li><b>Logging frameworks</b> holding references to logger instances</li>
82+
* <li><b>Thread pools</b> with threads created by loaded classes</li>
83+
* <li><b>Weak/Soft reference caches</b> not cleared on reload</li>
84+
* </ul>
85+
*
86+
* @see #close()
87+
* @see #isClosed()
2788
*/
2889
public class JClassLoader extends ClassLoader implements AutoCloseable {
2990
private final List<ClassSource> classSources;

0 commit comments

Comments
 (0)