RepoPilotOpen in app →

ronmamo/reflections

Java runtime metadata analysis

Mixed

Stale — last commit 2y ago

weakest axis
Use as dependencyConcerns

non-standard license (WTFPL); last commit was 2y ago

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 28+ active contributors
  • WTFPL licensed
  • CI configured
Show all 7 evidence items →
  • Tests present
  • Stale — last commit 2y ago
  • Concentrated ownership — top contributor handles 59% of recent commits
  • Non-standard license (WTFPL) — review terms
What would change the summary?
  • Use as dependency ConcernsMixed if: clarify license terms

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Forkable" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/ronmamo/reflections?axis=fork)](https://repopilot.app/r/ronmamo/reflections)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/ronmamo/reflections on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: ronmamo/reflections

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/ronmamo/reflections shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

WAIT — Stale — last commit 2y ago

  • 28+ active contributors
  • WTFPL licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y ago
  • ⚠ Concentrated ownership — top contributor handles 59% of recent commits
  • ⚠ Non-standard license (WTFPL) — review terms

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live ronmamo/reflections repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/ronmamo/reflections.

What it runs against: a local clone of ronmamo/reflections — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in ronmamo/reflections | Confirms the artifact applies here, not a fork | | 2 | License is still WTFPL | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 720 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>ronmamo/reflections</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of ronmamo/reflections. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/ronmamo/reflections.git
#   cd reflections
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of ronmamo/reflections and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "ronmamo/reflections(\\.git)?\\b" \\
  && ok "origin remote is ronmamo/reflections" \\
  || miss "origin remote is not ronmamo/reflections (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(WTFPL)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"WTFPL\"" package.json 2>/dev/null) \\
  && ok "license is WTFPL" \\
  || miss "license drift — was WTFPL at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "src/main/java/org/reflections/Reflections.java" \\
  && ok "src/main/java/org/reflections/Reflections.java" \\
  || miss "missing critical file: src/main/java/org/reflections/Reflections.java"
test -f "src/main/java/org/reflections/Configuration.java" \\
  && ok "src/main/java/org/reflections/Configuration.java" \\
  || miss "missing critical file: src/main/java/org/reflections/Configuration.java"
test -f "src/main/java/org/reflections/Store.java" \\
  && ok "src/main/java/org/reflections/Store.java" \\
  || miss "missing critical file: src/main/java/org/reflections/Store.java"
test -f "src/main/java/org/reflections/scanners/Scanner.java" \\
  && ok "src/main/java/org/reflections/scanners/Scanner.java" \\
  || miss "missing critical file: src/main/java/org/reflections/scanners/Scanner.java"
test -f "src/main/java/org/reflections/ReflectionUtils.java" \\
  && ok "src/main/java/org/reflections/ReflectionUtils.java" \\
  || miss "missing critical file: src/main/java/org/reflections/ReflectionUtils.java"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 720 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~690d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/ronmamo/reflections"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Reflections is a Java library that scans your classpath at runtime and indexes metadata, enabling reverse queries of the type system. It lets you find subtypes of a class, locate types annotated with specific annotations, discover methods with particular signatures, and identify classpath resources—all without needing to know type hierarchies beforehand. Modular structure: src/main/java/org/reflections/ contains the core Reflections.java engine with Store.java for caching results; scanners/ package (SubTypesScanner, TypeAnnotationsScanner, MethodAnnotationsScanner, etc.) implements pluggable metadata extraction; util/ provides ConfigurationBuilder, FilterBuilder, and query helpers; vfs/ abstracts filesystem/JAR traversal (Vfs.java, ZipDir, JarInputDir, SystemDir); serializers/ handle JSON/XML/Java code output.

👥Who it's for

Java developers building dependency injection frameworks (like Spring), plugin systems, or annotation-processing tools who need to discover classes and metadata dynamically at runtime without loading all classes upfront or requiring build-time code generation.

🌱Maturity & risk

Mature but unmaintained: last released version 0.10.2 (October 2021) with 257KB of Java code and established CI/CD via Travis and Maven workflows. However, the README explicitly states the library is 'NOT under active development or maintenance' with open issues and workarounds; production use should assume no future updates.

Significant maintenance risk: single maintainer (ronmamo) with no recent commits visible, unmaintained status declared in README, and Java 8 minimum (pom.xml <jdk.version>1.8</jdk.version>). Dependency on Javassist 3.28.0-GA (for bytecode scanning) may have unpatched vulnerabilities. Breaking changes between 0.9.x and 0.10+ suggest migration pain if the project ever resumes.

Active areas of work

No active development: repository is in maintenance mode with snapshot version 0.11-SNAPSHOT in pom.xml but no releases. GitHub workflows exist (maven-ci.yml) but likely stale. Contributors should assume this is a stable, frozen codebase accepting only critical bug fixes if PRs are submitted.

🚀Get running

git clone https://github.com/ronmamo/reflections.git
cd reflections
mvn clean install

This compiles with Maven, runs tests, and installs the JAR locally. No external services required.

Daily commands: No server/CLI. This is a library. Use it in your code:

Reflections reflections = new Reflections(
  new ConfigurationBuilder()
    .forPackage("com.example")
    .setScanners(SubTypes, TypesAnnotated));
Set<Class<?>> classes = reflections.get(SubTypes.of(MyInterface.class).asClass());

Or run tests: mvn test

🗺️Map of the codebase

  • src/main/java/org/reflections/Reflections.java — Main entry point and orchestrator—handles classpath scanning, configuration, and query execution; every contributor must understand the scanning lifecycle
  • src/main/java/org/reflections/Configuration.java — Core configuration abstraction—defines scanners, filters, and metadata sources; essential for understanding how to customize and extend Reflections
  • src/main/java/org/reflections/Store.java — In-memory metadata store—central data structure holding all scanned type/annotation/method metadata; critical for query performance and data retrieval
  • src/main/java/org/reflections/scanners/Scanner.java — Scanner interface contract—all metadata extraction delegates through this; required reading for extending Reflections with custom scanners
  • src/main/java/org/reflections/ReflectionUtils.java — Reflection query API—provides static predicates and filtering methods for runtime type system queries; heavily used by downstream code
  • src/main/java/org/reflections/util/ClasspathHelper.java — Classpath URL resolution—handles classpath scanning entry points for different runtime environments (JVM, containers); failure here blocks all scanning
  • pom.xml — Maven build config with Javassist and serialization dependencies; defines library boundaries and supported Java versions

🛠️How to make changes

Add a Custom Scanner

  1. Create a new scanner class extending AbstractScanner in src/main/java/org/reflections/scanners/ (src/main/java/org/reflections/scanners/AbstractScanner.java)
  2. Override scan(ClassFile) to extract metadata and call put(key, value) to store findings (src/main/java/org/reflections/scanners/SubTypesScanner.java)
  3. Register the scanner in Configuration by passing it to setScannersSupplier() or ConfigurationBuilder.setScanners() (src/main/java/org/reflections/util/ConfigurationBuilder.java)
  4. Query results using Reflections.getStore().get(indexKey) or add a fluent query helper in ReflectionUtils (src/main/java/org/reflections/ReflectionUtils.java)

Add a New Serialization Format

  1. Create a new serializer class implementing Serializer interface in src/main/java/org/reflections/serializers/ (src/main/java/org/reflections/serializers/Serializer.java)
  2. Implement save(Store, OutputStream) to write Store metadata in your chosen format (e.g., YAML, Protocol Buffers) (src/main/java/org/reflections/serializers/XmlSerializer.java)
  3. Implement read(InputStream) to reconstruct Store from serialized format (src/main/java/org/reflections/serializers/JsonSerializer.java)
  4. Pass serializer instance to Configuration via setSerializer() or ConfigurationBuilder (src/main/java/org/reflections/util/ConfigurationBuilder.java)

Add Support for a New Classpath Source

  1. Create Dir and File implementations in src/main/java/org/reflections/vfs/ for your classpath source (e.g., remote JARs, database) (src/main/java/org/reflections/vfs/Vfs.java)
  2. Implement Dir.getFiles() and File.getInputStream() to provide bytecode stream access (src/main/java/org/reflections/vfs/SystemDir.java)
  3. Register your VFS handler in Vfs.UrlType enum or via Vfs.addDefaultURLTypes() (src/main/java/org/reflections/vfs/UrlTypeVFS.java)
  4. Add classpath URL detection in ClasspathHelper to automatically discover your source type (src/main/java/org/reflections/util/ClasspathHelper.java)

Extend Query API with Custom Predicates

  1. Add static predicate method to ReflectionUtils (e.g., getMembersWithAnnotation) following existing pattern (src/main/java/org/reflections/ReflectionUtils.java)
  2. Use Reflections.getStore().get() with appropriate index keys to fetch metadata (src/main/java/org/reflections/Store.java)
  3. Implement filtering logic in ReflectionUtilsPredicates if using reflection-based matching (src/main/java/org/reflections/util/ReflectionUtilsPredicates.java)
  4. Add corresponding test cases in src/test/java/org/reflections/ReflectionUtilsTest.java (src/test/java/org/reflections/ReflectionUtilsTest.java)

🪤Traps & gotchas

Javassist bytecode parsing quirks: Reflections relies on Javassist to parse .class files; some JDK/module-system edge cases may not work (e.g., Java 9+ modules). Filter must match scanner scope: if you exclude a package in FilterBuilder but don't match the scanner's input filter, results will be incomplete—filtering applies to classpath traversal, not post-scan filtering. No support for nested/anonymous classes in all scanners: some scanners only detect top-level classes. JAR/ZIP handling: symlinks and nested ZIPs may not traverse correctly depending on JDK and OS. Store serialization format is fragile: JSON/XML serialized stores from 0.9.x may not deserialize in 0.10.x due to breaking changes. No parallel scanning: scanning is single-threaded; large classpaths may be slow.

🏗️Architecture

💡Concepts to learn

  • Bytecode introspection via Javassist — Reflections reads raw .class files without loading classes into the JVM, using Javassist's CtClass API to extract type metadata; critical for understanding why some metadata is available while others aren't
  • Virtual Filesystem (VFS) abstraction — The vfs/ package abstracts ZIPs, JARs, and filesystem directories behind a common interface to handle different classpath entry types uniformly; essential for understanding cross-platform classpath traversal
  • Type hierarchy discovery via ASM/constant pool parsing — SubTypesScanner extracts superclass and interface information from Java constant pool without loading classes; this inverse index enables fast 'find all subclasses' queries
  • Annotation metadata extraction — Multiple scanners (TypeAnnotationsScanner, MethodAnnotationsScanner) extract annotation instances from bytecode to enable 'find types annotated with @X' queries without reflection
  • Classpath scanning and indexing — Core strategy: scan once at startup, build in-memory index (Store), enable fast subsequent queries; trades startup time for query speed, common in DI frameworks
  • Plugin Scanner pattern — Reflections uses pluggable Scanner interface; different scanners extract different metadata types independently; enables extending functionality without modifying core
  • Transitive type queries (reverse lookups) — Reflections enables queries like 'all classes implementing Interface X' or 'all methods returning Type Y'—inverting the usual forward dependency resolution; critical for frameworks that discover implementations
  • spring-projects/spring-framework — Heavy internal user of classpath scanning for @Component/@Service discovery; Reflections provides an alternative if Spring's ClassPathScanningCandidateComponentProvider isn't sufficient
  • google/guice — Google's DI framework also needs runtime type discovery; Reflections and Guice solve the same problem in different ways
  • bill-burke/scannotations — Direct predecessor library mentioned in README that inspired Reflections; archived but historically important
  • classgraph/classgraph — Modern alternative to Reflections for classpath scanning; actively maintained and handles Java 9+ modules, recommended if starting new projects
  • javassist/javassist — Bytecode manipulation library that Reflections depends on; understanding Javassist APIs is essential for hacking Reflections internals

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive test coverage for VFS (Virtual File System) implementations

The vfs package contains 8 file system abstraction classes (JarInputDir, JbossDir, SystemDir, ZipDir, etc.) but there are no dedicated unit tests in src/test/java/org/reflections for these implementations. This is critical since VFS is the foundation for classpath scanning across different environments (JAR files, ZIP archives, JBoss VFS). Adding tests would catch platform-specific issues early and improve reliability for users on different app servers.

  • [ ] Create src/test/java/org/reflections/vfs/VfsTest.java with tests for Vfs.Dir and Vfs.File abstractions
  • [ ] Add VfsJarInputTest.java to test JAR file scanning in src/main/java/org/reflections/vfs/JarInputDir.java and JarInputFile.java
  • [ ] Add VfsZipTest.java to test ZIP file scanning for ZipDir.java and ZipFile.java implementations
  • [ ] Add test fixtures (sample JAR/ZIP files) to src/test/resources for reproducible testing

Add GitHub Actions CI workflow for Java 11+ and modernize from Travis CI

The repo still uses .travis.yml (legacy Travis CI) but has .github/workflows/maven-ci.yml suggesting a migration started. The pom.xml targets jdk.version=1.8 but doesn't test on modern Java versions (11, 17, 21+). The README states the library is 'NOT under active development' - a modern multi-version CI matrix would help attract contributors and ensure compatibility. This is especially important for classpath scanning which is JDK version-sensitive.

  • [ ] Enhance .github/workflows/maven-ci.yml to include matrix testing for Java 8, 11, 17, and 21
  • [ ] Add JDK compatibility test for module system (JPMS) changes in Java 9+
  • [ ] Add test for different OS environments (ubuntu-latest, windows-latest, macos-latest) since VFS behavior varies by platform
  • [ ] Remove or archive .travis.yml after confirming GitHub Actions workflow passes

Add integration tests for Scanner implementations with real-world classpath scenarios

The src/test/java has ReflectionsTest.java and ReflectionsCollectTest.java but scanners package (8 scanners: TypeAnnotationsScanner, SubTypesScanner, MethodParameterNamesScanner, etc.) lacks dedicated integration tests showing their combined behavior. The existing tests use CombinedTestModel.java and TestModel.java but don't test edge cases like module-info.class scanning, parameterized types with annotations, or scanning Spring/Guice annotated classes. This would help validate the library against popular frameworks.

  • [ ] Create src/test/java/org/reflections/scanners/ScannersIntegrationTest.java testing all scanner combinations
  • [ ] Add test case for MethodParameterNamesScanner.java with Java 8+ parameter name retention and reflection
  • [ ] Add test case for TypeAnnotationsScanner.java with meta-annotations and composed annotations
  • [ ] Add test model in src/test/java with Spring @Component/@Service/@Repository annotations to validate real-world framework compatibility

🌿Good first issues

  • Add unit tests for src/main/java/org/reflections/vfs/ classes (SystemDir, ZipDir, JarInputDir) with actual JAR/ZIP fixtures to improve coverage of VFS edge cases and ensure correct behavior across different Java versions.
  • Document the relationship between FilterBuilder package exclusions and each Scanner implementation's filtering behavior in README with a concrete example showing why excludePackage() doesn't always exclude query results.
  • Implement a ResourceUrlScanner (scanning for @Component or other Spring-like stereotypes) as a new Scanner in scanners/ to extend the library's use in Spring-adjacent frameworks, then add integration tests.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • f5514b1 — Delete dependabot.yml (ronmamo)
  • a566ac6 — ref-0.10.3 (#418) (ronmamo)
  • 0569496 — Update README.md (ronmamo)
  • f825f41 — Update README.md (ronmamo)
  • 8e7a5fb — Bump gson from 2.8.8 to 2.9.1 (#407) (dependabot[bot])
  • 1235fd9 — released 0.10.2 (ronma)
  • 5ff7a1d — ref-0.10.2 (#356) (ronmamo)
  • e9ed4e1 — Dependabot 202110 (#349) (ronmamo)
  • b7e8f9a — ref-0.10.1 - fix exception, docs, ci matrix, dependabot (ronmamo)
  • ee52a9d — readme gh-pages (ronma)

🔒Security observations

  • High · Unmaintained Library with Known Vulnerabilities — Project root / README.md. The Reflections library is explicitly stated as NOT under active development or maintenance (as noted in README). Last released version is 0.11-SNAPSHOT, with last stable release being 0.10.2 from October 2021. This means security vulnerabilities discovered after this date will not be patched. Fix: Consider migrating to actively maintained alternatives or establishing an internal maintenance plan. Review all known CVEs for Reflections and its dependencies.
  • High · Outdated Javassist Dependency — pom.xml - javassist.version property. The project depends on Javassist 3.28.0-GA (released 2021). This is a bytecode manipulation library used for runtime metadata analysis. Older versions may contain known vulnerabilities in bytecode processing that could be exploited through crafted class files. Fix: Update to the latest stable version of Javassist (currently 3.30.x or later). Audit for CVEs in 3.28.0-GA and review security implications of bytecode manipulation.
  • High · Unsafe VFS Implementation - Multiple File System Access Points — src/main/java/org/reflections/vfs/ (all VFS implementation files). The codebase contains multiple virtual file system (VFS) implementations (SystemDir, ZipDir, JarInputDir, JbossDir) that read and parse file system resources. These implementations may be vulnerable to path traversal attacks if not properly validating input paths, particularly in JarInputDir, ZipDir, and SystemDir classes. Fix: Implement strict path validation and canonicalization. Use Java's Path API with security checks. Prevent directory traversal using '..' sequences. Add unit tests for path traversal attempts.
  • High · Arbitrary Code Execution Risk via Serialization — src/main/java/org/reflections/serializers/ (all serializer classes). The project includes multiple serializers (JsonSerializer, XmlSerializer, JavaCodeSerializer) that deserialize metadata. JavaCodeSerializer in particular generates and potentially executes Java code. Deserialization of untrusted data could lead to arbitrary code execution. Fix: Implement strict input validation for all serialized data. Use safe deserialization practices. Never deserialize data from untrusted sources. Consider removing JavaCodeSerializer or restricting its use to trusted contexts only.
  • Medium · Reflection-based Access to Private Members — src/main/java/org/reflections/ReflectionUtils.java. The ReflectionUtils class provides utilities to access and manipulate private class members via reflection. While this is the library's intended purpose, it can be misused in security-sensitive contexts to bypass access controls and access sensitive data. Fix: Document security implications clearly. Recommend users apply SecurityManager restrictions in sensitive environments. Consider adding a security-aware configuration option to restrict reflection capabilities.
  • Medium · Classpath Scanning Without URL Validation — src/main/java/org/reflections/util/ClasspathHelper.java. ClasspathHelper scans the classpath which may include URLs from untrusted sources (e.g., shared classpaths in multi-tenant environments). No apparent validation of URL sources before processing. Fix: Implement URL whitelist validation. Add configuration options to restrict which classpath URLs can be scanned. Log all classpath sources being scanned for audit trails.
  • Medium · Potential XML External Entity (XXE) Vulnerability — src/main/java/org/reflections/serializers/XmlSerializer.java. The XmlSerializer class parses XML metadata. If XML parsing is not configured to disable external entity resolution, it could be vulnerable to XXE attacks when processing malicious serialized XML data. Fix: Disable XXE processing in XML parser configuration. Use safe XML parsing practices: disable DOCTYPE declarations, external entities, external DTDs, and parameter entities.
  • Low · Missing Input Validation in FilterBuilder — src/main/java/org/reflections/util/FilterBuilder.java. FilterBuilder accepts pattern-based filters for classpath scanning. Insufficient validation of filter patterns could lead to ReDoS (Regular Expression Denial of Service) attacks with maliciously crafted patterns. Fix: Add regex pattern validation

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · ronmamo/reflections — RepoPilot