Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Luke Hutchison edited this page Mar 5, 2024 · 7 revisions

See also the ClassGraph API overview.

Contents

ScanResult

The .scan() method produces a ScanResult, which can be queried for either classes or resources (or both).

🛑 Make sure you call ScanResult#close() when you have finished with the ScanResult, or allocate the ScanResult in a try-with-resources block -- see ScanResult lifecycle below.

try (ScanResult scanResult = new ClassGraph().enableAllInfo().scan()) {
    // ...
}

A ScanResult holds all the ClassInfo objects and Resource objects found during a scan:

  • Classes: (N.B. call .enableClassInfo() before .scan(), and call .ignoreClassVisibility() if you want to scan non-public classes.)

    • Querying for a specific named class:
      • .getClassInfo(String className) returns the ClassInfo object for the named class, or returns null if the named class was not found during the scan.
    • Querying for all classes of a given type: Except where indicated, these methods return a ClassInfoList of ClassInfo objects representing the classes.

      💡 A ClassInfoList can be further filtered by calling .filter(ClassInfoFilter).

      • .getAllClasses() returns a list of all classes, interfaces and annotations found during the scan.
      • .getAllClassesAsMap() returns a Map<String, ClassInfo> from class name to ClassInfo for all classes, interfaces and annotations found during the scan.
      • .getAllStandardClasses() returns a list of all standard classes (non-annotation, non-interface classes).
      • .getAllAnnotations() returns a list of all annotations.
      • .getAllInterfaces() returns a list of all non-annotation interfaces. (Annotations are interfaces, and can be implemented.)
      • .getAllInterfacesAndAnnotations() returns a list of all interfaces and annotations (i.e. everything that can be implemented.)
      • .getAllEnums() returns a list of all Enum classes.
      • .getAllRecords() returns a list of all record types (JDK 14+).
    • Querying for all classes related to a named class: These methods look up the named class by calling getClassInfo(className), then if the result is non-null, call the corresponding method in the resulting ClassInfo, returning a ClassInfoList, or the empty list if no results.
      • .getSubclasses(String className | Class<?> superclassRef) returns a list of classes that extend the given superclass.
      • .getSuperclasses(String className | Class<?> subclassRef) returns a list of superclasses of the given class.
      • .getInterfaces(String className | Class<?> classRef) returns a list of interfaces implemented by a given class or by one of its superclasses, if this is a standard class, or the superinterfaces extended by this interface, if the class is an interface.
      • .getClassesImplementing(String interfaceName | Class<?> interfaceRef) returns a list of classes that implement (or have superclasses that implement) the given interface (or one of its subinterfaces).
      • .getClassesWithAnnotation(String annotationClassName | Class<? extends Annotation> annotationClassRef) returns a list of classes with the given class annotation or meta-annotation.
      • .getClassesWithAnyAnnotation(String... annotationClassName | Class<? extends Annotation>... annotationClassRef) returns a list of classes with any of the the given class annotations or meta-annotations (uses an OR operator).
      • .getClassesWithAllAnnotations(String... annotationClassName | Class<? extends Annotation>... annotationClassRef) returns a list of classes with all of the the given class annotations or meta-annotations (uses an AND operator).
      • .getAnnotationsOnClass(String className) returns a list of annotations on the named class. (N.B. call .enableAnnotationInfo() before .scan(), and call .ignoreClassVisibility() if you want to scan non-public annotations.)
      • .getClassesWithMethodAnnotation(String annotationClassName | Class<? extends Annotation> annotationClassRef) returns a list of classes that have a method with an annotation of the given type. (N.B. call .enableAnnotationInfo() and .enableMethodInfo() before .scan(), and call .ignoreClassVisibility() and/or .ignoreMethodVisibility() if you want to scan non-public annotations and/or non-public methods.)
      • .getClassesWithMethodParameterAnnotation(String paramAnnotationClassName | Class<? extends Annotation> paramAnnotationClassRef) returns a list of classes that have a method with a method parameter annotation of the given type. (N.B. call .enableAnnotationInfo() and .enableMethodInfo() before .scan(), and call .ignoreClassVisibility() and/or .ignoreMethodVisibility() if you want to scan non-public annotations and/or non-public methods.)
      • .getClassesWithFieldAnnotation(String annotationClassName | Class<? extends Annotation> annotationClassRef) returns a list of classes that have a field with an annotation of the given type. (N.B. call .enableAnnotationInfo() and .enableFieldInfo() before .scan(), and call .ignoreClassVisibility() and/or .ignoreFieldVisibility() if you want to scan non-public annotations and/or non-public fields.)
  • Finding all inter-class dependencies: The following methods enable you to find dependencies between classes, by looking for class references in superclasses, interfaces, methods, fields, annotations, local variables, intermediate values within a method's code, concrete type parameters, etc.

    💡 Call ClassGraph ClassGraph#enableInterClassDependencies() before #scan() to enable the following methods; you can also call ClassGraph#enableExternalClasses() if you want non-accepted classes in the results.

    💡 See also ClassInfo#getClassDependencies() and ClassInfoList#generateGraphVizDotFileFromClassDependencies().

    • ScanResult#getClassDependencyMap() returns a Map<ClassInfo, ClassInfoList> mapping a class to the classes it depends upon.
    • ScanResult#getReverseClassDependencyMap() returns a Map<ClassInfo, ClassInfoList> mapping a class to the classes that depend upon it.
  • Packages:

    • .getPackageInfo() returns a PackageInfoList of PackageInfo objects for all packages found while scanning.
    • .getPackageInfo(String packageName) returns the PackageInfo object for the named package, or null if the package was not found.
  • Modules:

    • .getModuleInfo() returns a ModuleInfoList of ModuleInfo objects for all modules found while scanning.
    • .getModuleInfo(String moduleName) returns the ModuleInfo object for the named module, or null if the module was not found.
  • Resources: Except where indicated, these methods return a ResourceList consisting of Resource objects for all the relevant file resources found in accepted paths or packages during the scan.

    💡 A ResourceList can be further filtered by calling .filter(ResourceFilter).

    • .getAllResources() returns a list of all Resource objects (including both classfiles an non-classfiles) found in accepted packages during the scan.
    • .getAllResourcesAsMap() returns a Map<String, ResourceList> mapping from a resource path to Resource for all resources (classfiles and non-classfiles) found in accepted packages during the scan. There can be more that one resource with a given path, if multiple classpath or module path elements contain resources with the same path.
    • .getResourcesWithPath(String resourcePath) returns a list of all resources with the given path (e.g. "META-INF/config/config.xml") in accepted paths or packages.
    • .getResourcesWithPathIgnoringAccept(String resourcePath) returns a list of all resources with the given path (e.g. "META-INF/config/config.xml") in any classpath element, ignoring path or package accept criteria (i.e. will return resources whether or not they are accepted, as long as they are not rejected).
    • .getResourcesWithLeafName(String leafName) returns a list of all resources with the given leafname (e.g. "config.xml") in accepted paths or packages.
    • .getResourcesWithExtension(String extension) returns a list of all resources with the given extension (e.g. "xml") in accepted paths or packages.
    • .getResourcesMatchingWildcard(String wildcardString) returns a list of all resources with paths matching the given wildcard string (which may contain globs) in accepted paths or packages. The syntax is * to match zero or more of any character other than /, ** to match zero or more of any character, ? to match one of any character, and any other Java regex syntax (such as character ranges in square brackets), with the exception of ., which is escaped before the string is passed to the regex parser.
    • .getResourcesMatchingPattern(Pattern pattern) returns a list of all resources with paths matching the given pattern in accepted paths or packages.
  • Serialization to JSON / deserialization from JSON: A ScanResult can also be serialized/deserialized for build-time scanning or annotation processing, e.g. for providing Android compatibility, since ClassGraph cannot read Dalvik classfiles. (Note though that if all you need is a list of classes that satisfy certain criteria, it is much more efficient to just store the list of class names of matching classes to a file, rather than the entire serialized ScanResult.) The serialized JSON can also be used for debugging, to quickly examine what ClassGraph found through the scan.

    • scanResult.toJSON([int indentWidth]) serializes the ScanResult to JSON.
    • ScanResult.fromJSON(String jsonStr) deserializes from a JSON string, returning a ScanResult.
  • Classpath resolution: You can obtain a list of all the classpath elements that were scanned. (N.B. these same four methods are defined in both ClassGraph and ScanResult, except that the ClassGraph versions do not extract nested jarfiles, but the ScanResult versions do return URLs/files for nested jars, if any nested jars were extracted during classpath scanning.)

    • .getClasspath(), returns the classpath as a path String separated by File.pathSeparatorChar. Returns only the base file of each classpath entry (i.e. will not include compound URLs with package roots within a jar, or nested jars within jars, since the URL scheme separator char and the path separator char are both : on Linux and Mac OS X).
    • .getClasspathFiles(), returns classpath entries as a List<File>. Returns only the base file of each classpath entry (i.e. will not include compound URLs with package roots within a jar, or nested jars within jars).
    • .getClasspathURIs(), returns classpath entries and modules as a List<URI>.
    • .getClasspathURLs(), returns classpath as a List<URL>. Will not include jrt: URIs for system modules or modules obtained from a jlink'd runtime image, since URL does not support the jrt: scheme.
    • .getModules(), returns all visible modules as a List<ModuleRef> of ModuleRef objects (which is a JDK 7/8-compatible wrapper for JPMS' ModuleReference).
    • .getModulePathInfo() returns information about the module path, as specified on the commandline using with --module-path, --add-modules, --patch-module, --add-exports, --add-opens, and --add-reads, and as also found in Add-Exports and Add-Opens entries found in manifest files during scanning, as a ModulePathInfo object.
  • Freeing resources:

    • .close() manually frees all resources used by the ScanResult, including deleting any temporary files created by unzipping nested jars. If you don't manually close the ScanResult, then these resources will be freed/deleted by a shutdown hook.

ScanResult lifecycle

Important: The ScanResult should be assigned in a try-with-resources block or equivalent to free resources allocated during the scan as soon as they are no longer needed (including closing or unmapping open or mapped files, deleting any temporary files that had to be created to read nested jars, closing module references, and freeing memory).

🛑 After the ScanResult is closed, any further calls to its methods will throw an IllegalArgumentException. This also applies to many methods in other objects obtained from the ScanResult, such as ClassInfo, FieldInfo, MethodInfo, etc. -- so make sure you extract all the information you need from the ScanResult within the try-with-resources block, and store it in your own data structures, rather than keeping references to objects provided by ClassGraph outside the try-with-resources block.

try-with-resources in Java:

try (ScanResult scanResult = new ClassGraph().scan()) {
    // Use scanResult here
}

.use { ... } in Kotlin:

ClassGraph().scan().use { scanResult ->
    // Use scanResult here
}

.withCloseable { ... } in Groovy:

new ClassGraph().scan().withCloseable { scanResult ->
    // Use scanResult here
}

finally block in Scala:

Scala does not yet have try-with-resources. You will need to close the ScanResult in a finally block. It is best to put val scanResult = ... inside a block too, so that the reference is not still visible after the finally block is executed.

{
  val scanResult = new ClassGraph().scan()
  try {
      // Use scanResult here
  } finally {
      scanResult.close()
  }
}

Closing all ScanResult instances

If you want to close all open (unclosed) ScanResult instances at once, you can call the static method ScanResult.closeAll(). To be safe (to ensure you don't leak any resources), you might want to call this on container unload/destroy in a containerized runtime.

Note that if you call ScanResult.closeAll(), you need to ensure that the lifecycle of the classloader matches the lifecycle of your application, or that two concurrent applications don't share the same classloader, since this is a static method -- otherwise one application might close another application's ScanResult instances while they are still in use.

Clone this wiki locally
Morty Proxy This is a proxified and sanitized view of the page, visit original site.