FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Classpath Specification Mechanisms · classgraph/classgraph Wiki · GitHub

Classpath Specification Mechanisms

Luke Hutchison edited this page Aug 28, 2026 · 67 revisions

Classpath and module path finding is implemented by the classgraph-classpath library, which can also be used on its own, without scanning anything -- see the Classpath API. The following mechanisms are handled:

  • The module path (Project Jigsaw), using this mechanism to find all visible modules.

    • Can find all modules visible from the calling code's module layer: modules in the module path, system modules, and modules in jlink'd images.
    • Includes support for automatic modules, non-modular jars on the module path whose module name is derived from the Automatic-Module-Name entry in the manifest file, or from the filename of the jar. (The module name is found by ClassGraph whether these jars are added to the module path or the traditional classpath. A jar on the traditional classpath is in the unnamed module at runtime, so it has no ModuleReference, but it is still reported under the name it declares, or failing that under the name that would be derived from its filename.)
  • Multi-release jars on the traditional classpath, emulating the JPMS semantics for overriding the "base section" using "versioned sections" contained in paths of the form META-INF/versions/X, where X is an integer greater than or equal to 9, and less than or equal to the running JVM version. (N.B. This requires the manifest file to contain the attribute Multi-Release: true.)

  • The standard (now legacy) Java URLClassLoader and subclasses.

  • The java.class.path system property, supporting specification of the classpath using the -cp JRE commandline switch.

  • ClassGraph includes reflection code to extract path entries from specific classloaders from a wide range of common runtime environments:

    • The Spring, Spring-Boot, and Spring-Boot executable jar classloaders, including properly handling nested classpaths (jars within jars) in an optimal way, by "slicing" the jarfile to extract entries directly from nested jars (which is what Spring Boot also does for speed).
      • Also works with Spring Boot Dev Tools' RestartClassLoader for hot reload (though you will have to run a new scan on each restart).
      • Understands the nested: URL protocol that Spring Boot 3.2 and later use to address entries within an executable jar or war, e.g. jar:nested:/path/to/app.jar/!BOOT-INF/lib/dependency.jar!/.
    • The JBoss WildFly classloader, including JARs and WARs nested inside EARs.
    • The WebLogic classloader.
    • The OSGi Eclipse DefaultClassLoader.
    • The OSGi Equinox classloader (e.g. for Eclipse PDE).
    • The Apache Felix (OSGi reimplementation) classloader.
    • The traditional Websphere classloader.
    • The Websphere Liberty / Open Liberty classloader, in both war and overlay mode.
    • The Tomcat 8+ / Catalina WebappClassLoaderBase classloader and its subclasses.
    • The TomEE classloaders for servlets and JAX-RS endpoints (TomEEWebappClassLoader and CxfContainerClassLoader).
    • The Ant classloader.
    • The Plexus ClassWorlds ClassRealm classloader.
    • The Quarkus RuntimeClassLoader.
    • The Uno-Jar JarClassLoader, and the (older, unmaintained) One-Jar JarClassLoader.
    • Any unknown classloader with a predictable method such as getClasspath(), getClassPath(), getURLs() etc. (a number of method and field names are tried).
    • Any other classloader, by writing a ClassLoaderHandler for it and registering it with .registerClassLoaderHandler(handler) before scanning -- see the ClassGraph constructor API. (If you write a handler for a classloader that others are likely to hit, please consider contributing it.)
  • Remotely-hosted jarfiles, specified using http:// or https:// URLs. (Some ClassLoaders allow this.) This is disabled by default for security reasons, along with ftp: and mailto: -- a classpath is not always something you wrote. If .enableRemoteJarScanning() is called before .scan(), any remote jars are downloaded to a ByteBuffer in RAM, or if the jar is too large, the jar is spilled over to a temporary file on disk. (Note that if your classpath contains remote jars, they will be downloaded every time the classpath is scanned. Both ClassGraph and the context ClassLoader may separately download the same jarfiles.)

  • Jarfiles specified using custom URL schemes. A scheme the application has registered a URLStreamHandler or a java.nio.file.spi.FileSystemProvider for is scanned without being enabled -- registering the handler is already the statement that those URLs are meant to be read, and there is no way to enumerate the registered schemes to check. If a custom URI scheme is not backed by an underlying FileSystem implementation, then URL.openConnection() is used to open the URL, and if the data fetched over the connection is large, it will automatically spill to a temporary file on disk. Naming the scheme with .enableURLScheme("jimfs") is still worthwhile if you pass a ':'-separated classpath string to .enableClasspathEntries(String), since that is what keeps the string from being split at the scheme's own colon.

  • Classpath elements hosted on custom filesystems such as Jimfs. Supports scanning a classpath URL of custom scheme (e.g. jimfs://) via the NIO Files and Path APIs. This works for URLs that point to either a jarfile or to a directory (ClassGraph figures out which of these the URL points to). If you specify the URL path to a jarfile on a custom filesystem, it will be opened using FileChannel for speed, rather than calling URL.openConnection().

  • Wildcarded classpath entries, e.g. lib/* (which includes all jars and directories in lib/ as separate classpath entries), which is allowed as of JDK 6. (Only whole-directory globs are currently supported, so lib/proj* doesn't work, but this should match the JRE's behavior.)

  • Class-Path entries in a jarfile's manifest file, whereby jarfiles may add other external jarfiles to their own classpaths, with paths resolved relative to the parent directory or parent jarfile of the manifest's jarfile. ClassGraph is able to determine the transitive closure of these references, breaking cycles if necessary.

  • Bundle-ClassPath entries in an OSGi bundle jarfile's manifest file, which allows a bundle to add nested jars to the bundle classpath, with paths resolved relative to the root of the bundle jarfile.

  • Jarfiles within jarfiles (to unlimited nesting depth), e.g.
    project.jar!/BOOT-INF/lib/dependency.jar, as required by Spring-Boot, JBoss, and Felix classloaders, and probably others.

    • To accomplish this, ClassGraph implements a custom highly-optimized zipfile central directory parser, which is capable of handling zipfile "slices" (zipfiles nested within zipfiles, when the inner zipfile is stored rather than deflated), to arbitrary nesting depth. This allows ClassGraph to scan nested jarfiles (jarfiles within jarfiles, e.g. Spring Boot lib jars in BOOT-INF/lib/) without first extracting the inner jars to temporary files (the Java ZipFile API is not capable of this).
    • If nested jarfiles are deflated rather than stored (which is rare), they cannot be read as a slice since they are compressed, so these jarfiles are automatically inflated to RAM (with failover to a temporary file on disk if the nested jar is over 32MB in uncompressed size).
  • Zip64-format jarfiles

    • ClassGraph's custom jarfile reader has full support for Zip64. This extension of the zip file format is triggered if a jarfile contains more than 65536 entries, or any entry is over 4GB in uncompressed size, or the entire jar is over 4GB in size.
    • ClassGraph's jarfile reader contains workarounds for the Java ByteBuffer and array size limit of 2GB, by reading or mmap'ing large jarfiles in 2GB chunks, and seamlessly swapping in new chunks as needed.
  • The package hierarchy being rooted at a non-root path within a jarfile, e.g. BOOT-INF/classes/ (Spring Boot), WEB-INF/classes/ (Tomcat), and classes/ (Ant). Name the package root as part of the classpath entry, e.g. app.jar!/BOOT-INF/classes, and the entries below it are reported relative to it. (Note that the standard Java classloaders do not support this.)

  • Nested package roots and nested lib jars that a classloader looks for on its own. A classloader loads classes from the classpath elements it was given, and URLClassLoader -- the classloader every other one is measured against -- has no automatic package roots or lib dirs at all, so ClassGraph assumes none either. A directory called classes inside a classpath element is a package named classes, not a package root, unless the classloader that yielded that element has its own code that goes looking there. Two of the supported classloaders do:

    • Tomcat's WebappClassLoaderBase serves a webapp's own classes from WEB-INF/classes/, and mounts every jarfile in WEB-INF/lib/, without listing either as a classpath element of its own.
    • Uno-Jar and One-JAR's JarClassLoader loads from every jarfile under main/, which holds the jarfile it launches, and under lib/, which holds the jarfiles that jarfile depends upon.

    Jarfiles in a subdirectory of a lib dir are found too, since a classloader that adds the jarfiles of a lib dir looks below it as well. A Spring Boot application needs no automatic package root: its launcher hands its classloader an explicit URL for BOOT-INF/classes and one for each jarfile in BOOT-INF/lib, so both are ordinary classpath elements. An OSGi bundle likewise names the jarfiles it loads from in its Bundle-ClassPath manifest attribute, which ClassGraph reads. A ClassLoaderHandler you write yourself can declare package roots and lib dirs of its own -- see ClassGraph#registerClassLoaderHandler().

  • Handles both PARENT_FIRST and PARENT_LAST classloader delegation modes (used by Websphere and Spring Boot), in order to resolve classpath elements in the correct order, mirroring the delegation order of the classloaders that the classpath elements were obtained from. (Standard Java classloaders use PARENT_FIRST delegation.)

Wiki pages Pages 23

Clone this wiki locally


Back | FazBrowse Home | New Git URL