Class Classfile


  • class Classfile
    extends java.lang.Object
    A classfile binary format parser. Implements its own buffering to avoid the overhead of using DataInputStream. This class should only be used by a single thread at a time, but can be re-used to scan multiple classfiles in sequence, to avoid re-allocating buffer memory.

    See the class file format spec.

    • Field Detail

      • classpathElement

        private final ClasspathElement classpathElement
        The classpath element that contains this classfile.
      • classpathOrder

        private final java.util.List<ClasspathElement> classpathOrder
        The classpath order.
      • relativePath

        private final java.lang.String relativePath
        The relative path to the classfile (should correspond to className).
      • classfileResource

        private final Resource classfileResource
        The classfile resource.
      • stringInternMap

        private final java.util.concurrent.ConcurrentHashMap<java.lang.String,​java.lang.String> stringInternMap
        The string intern map.
      • className

        private java.lang.String className
        The name of the class.
      • minorVersion

        private int minorVersion
        The minor version of the classfile format.
      • majorVersion

        private int majorVersion
        The major version of the classfile format.
      • isExternalClass

        private final boolean isExternalClass
        Whether this is an external class.
      • classModifiers

        private int classModifiers
        The class modifiers.
      • isInterface

        private boolean isInterface
        Whether this class is an interface.
      • isRecord

        private boolean isRecord
        Whether this class is a record.
      • isAnnotation

        private boolean isAnnotation
        Whether this class is an annotation.
      • superclassName

        private java.lang.String superclassName
        The superclass name. (can be null if no superclass, or if superclass is rejected.)
      • implementedInterfaces

        private java.util.List<java.lang.String> implementedInterfaces
        The implemented interfaces.
      • fullyQualifiedDefiningMethodName

        private java.lang.String fullyQualifiedDefiningMethodName
        The fully qualified name of the defining method.
      • refdClassNames

        private java.util.Set<java.lang.String> refdClassNames
        Referenced class names.
      • fieldInfoList

        private FieldInfoList fieldInfoList
        The field info list.
      • methodInfoList

        private MethodInfoList methodInfoList
        The method info list.
      • typeSignatureStr

        private java.lang.String typeSignatureStr
        The type signature.
      • sourceFile

        private java.lang.String sourceFile
        The source file, such as Classfile.java
      • acceptedClassNamesFound

        private final java.util.Set<java.lang.String> acceptedClassNamesFound
        The names of accepted classes found in the classpath while scanning paths within classpath elements.
      • classNamesScheduledForExtendedScanning

        private final java.util.Set<java.lang.String> classNamesScheduledForExtendedScanning
        The names of external (non-accepted) classes scheduled for extended scanning (where scanning is extended upwards to superclasses, interfaces and annotations).
      • additionalWorkUnits

        private java.util.List<Scanner.ClassfileScanWorkUnit> additionalWorkUnits
        Any additional work units scheduled for scanning.
      • scanSpec

        private final ScanSpec scanSpec
        The scan spec.
      • cpCount

        private int cpCount
        The number of constant pool entries plus one.
      • entryOffset

        private int[] entryOffset
        The byte offset for the beginning of each entry in the constant pool.
      • entryTag

        private int[] entryTag
        The tag (type) for each entry in the constant pool.
      • indirectStringRefs

        private int[] indirectStringRefs
        The indirection index for String/Class entries in the constant pool.
      • NO_ANNOTATIONS

        private static final AnnotationInfo[] NO_ANNOTATIONS
        An empty array for the case where there are no annotations.
    • Constructor Detail

      • Classfile

        Classfile​(ClasspathElement classpathElement,
                  java.util.List<ClasspathElement> classpathOrder,
                  java.util.Set<java.lang.String> acceptedClassNamesFound,
                  java.util.Set<java.lang.String> classNamesScheduledForExtendedScanning,
                  java.lang.String relativePath,
                  Resource classfileResource,
                  boolean isExternalClass,
                  java.util.concurrent.ConcurrentHashMap<java.lang.String,​java.lang.String> stringInternMap,
                  WorkQueue<Scanner.ClassfileScanWorkUnit> workQueue,
                  ScanSpec scanSpec,
                  LogNode log)
           throws java.io.IOException,
                  Classfile.ClassfileFormatException,
                  Classfile.SkipClassException
        Directly examine contents of classfile binary header to determine annotations, implemented interfaces, the super-class etc. Creates a new ClassInfo object, and adds it to classNameToClassInfoOut. Assumes classpath masking has already been performed, so that only one class of a given name will be added.
        Parameters:
        classpathElement - the classpath element
        classpathOrder - the classpath order
        acceptedClassNamesFound - the names of accepted classes found in the classpath while scanning paths within classpath elements.
        classNamesScheduledForExtendedScanning - the names of external (non-accepted) classes scheduled for extended scanning (where scanning is extended upwards to superclasses, interfaces and annotations).
        relativePath - the relative path
        classfileResource - the classfile resource
        isExternalClass - if this is an external class
        stringInternMap - the string intern map
        workQueue - the work queue
        scanSpec - the scan spec
        log - the log
        Throws:
        java.io.IOException - If an IO exception occurs.
        Classfile.ClassfileFormatException - If a problem occurs while parsing the classfile.
        Classfile.SkipClassException - if the classfile needs to be skipped (e.g. the class is non-public, and ignoreClassVisibility is false)
    • Method Detail

      • scheduleScanningIfExternalClass

        private void scheduleScanningIfExternalClass​(java.lang.String className,
                                                     java.lang.String relationship,
                                                     LogNode log)
        Extend scanning to a superclass, interface or annotation.
        Parameters:
        className - the class name
        relationship - the relationship type
        log - the log
      • extendScanningUpwardsFromAnnotationParameterValues

        private void extendScanningUpwardsFromAnnotationParameterValues​(java.lang.Object annotationParamVal,
                                                                        LogNode log)
        Check if scanning needs to be extended upwards from an annotation parameter value.
        Parameters:
        annotationParamVal - the AnnotationInfo object for an annotation, or for an annotation parameter value.
        log - the log
      • extendScanningUpwards

        private void extendScanningUpwards​(LogNode log)
        Check if scanning needs to be extended upwards to an external superclass, interface or annotation.
        Parameters:
        log - the log
      • link

        void link​(java.util.Map<java.lang.String,​ClassInfo> classNameToClassInfo,
                  java.util.Map<java.lang.String,​PackageInfo> packageNameToPackageInfo,
                  java.util.Map<java.lang.String,​ModuleInfo> moduleNameToModuleInfo)
        Link classes. Not threadsafe, should be run in a single-threaded context.
        Parameters:
        classNameToClassInfo - map from class name to class info
        packageNameToPackageInfo - map from package name to package info
        moduleNameToModuleInfo - map from module name to module info
      • intern

        private java.lang.String intern​(java.lang.String str)
        Intern a string.
        Parameters:
        str - the str
        Returns:
        the string
      • getConstantPoolStringOffset

        private int getConstantPoolStringOffset​(int cpIdx,
                                                int subFieldIdx)
                                         throws Classfile.ClassfileFormatException
        Get the byte offset within the buffer of a string from the constant pool, or 0 for a null string.
        Parameters:
        cpIdx - the constant pool index
        subFieldIdx - should be 0 for CONSTANT_Utf8, CONSTANT_Class and CONSTANT_String, and for CONSTANT_NameAndType_info, fetches the name for value 0, or the type descriptor for value 1.
        Returns:
        the constant pool string offset
        Throws:
        Classfile.ClassfileFormatException - If a problem is detected
      • getConstantPoolString

        private java.lang.String getConstantPoolString​(int cpIdx,
                                                       boolean replaceSlashWithDot,
                                                       boolean stripLSemicolon)
                                                throws Classfile.ClassfileFormatException,
                                                       java.io.IOException
        Get a string from the constant pool, optionally replacing '/' with '.'.
        Parameters:
        cpIdx - the constant pool index
        replaceSlashWithDot - if true, replace slash with dot in the result.
        stripLSemicolon - if true, strip 'L' from the beginning and ';' from the end before returning (for class reference constants)
        Returns:
        the constant pool string
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • getConstantPoolString

        private java.lang.String getConstantPoolString​(int cpIdx,
                                                       int subFieldIdx)
                                                throws Classfile.ClassfileFormatException,
                                                       java.io.IOException
        Get a string from the constant pool.
        Parameters:
        cpIdx - the constant pool index
        subFieldIdx - should be 0 for CONSTANT_Utf8, CONSTANT_Class and CONSTANT_String, and for CONSTANT_NameAndType_info, fetches the name for value 0, or the type descriptor for value 1.
        Returns:
        the constant pool string
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • getConstantPoolString

        private java.lang.String getConstantPoolString​(int cpIdx)
                                                throws Classfile.ClassfileFormatException,
                                                       java.io.IOException
        Get a string from the constant pool.
        Parameters:
        cpIdx - the constant pool index
        Returns:
        the constant pool string
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • getConstantPoolStringFirstByte

        private byte getConstantPoolStringFirstByte​(int cpIdx)
                                             throws Classfile.ClassfileFormatException,
                                                    java.io.IOException
        Get the first UTF8 byte of a string in the constant pool, or '\0' if the string is null or empty.
        Parameters:
        cpIdx - the constant pool index
        Returns:
        the first byte of the constant pool string
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • getConstantPoolClassName

        private java.lang.String getConstantPoolClassName​(int cpIdx)
                                                   throws Classfile.ClassfileFormatException,
                                                          java.io.IOException
        Get a string from the constant pool, and interpret it as a class name by replacing '/' with '.'.
        Parameters:
        cpIdx - the constant pool index
        Returns:
        the constant pool class name
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • getConstantPoolClassDescriptor

        private java.lang.String getConstantPoolClassDescriptor​(int cpIdx)
                                                         throws Classfile.ClassfileFormatException,
                                                                java.io.IOException
        Get a string from the constant pool representing an internal string descriptor for a class name ("Lcom/xyz/MyClass;"), and interpret it as a class name by replacing '/' with '.', and removing the leading "L" and the trailing ";".
        Parameters:
        cpIdx - the constant pool index
        Returns:
        the constant pool class descriptor
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • constantPoolStringEquals

        private boolean constantPoolStringEquals​(int cpIdx,
                                                 java.lang.String asciiStr)
                                          throws Classfile.ClassfileFormatException,
                                                 java.io.IOException
        Compare a string in the constant pool with a given ASCII string, without constructing the constant pool String object.
        Parameters:
        cpIdx - the constant pool index
        asciiStr - the ASCII string to compare to
        Returns:
        true, if successful
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • cpReadInt

        private int cpReadInt​(int cpIdx)
                       throws java.io.IOException
        Read an int from the constant pool.
        Parameters:
        cpIdx - the constant pool index.
        Returns:
        the int
        Throws:
        java.io.IOException - If an I/O exception occurred.
      • cpReadLong

        private long cpReadLong​(int cpIdx)
                         throws java.io.IOException
        Read a long from the constant pool.
        Parameters:
        cpIdx - the constant pool index.
        Returns:
        the long
        Throws:
        java.io.IOException - If an I/O exception occurred.
      • getFieldConstantPoolValue

        private java.lang.Object getFieldConstantPoolValue​(int tag,
                                                           char fieldTypeDescriptorFirstChar,
                                                           int cpIdx)
                                                    throws Classfile.ClassfileFormatException,
                                                           java.io.IOException
        Get a field constant from the constant pool.
        Parameters:
        tag - the tag
        fieldTypeDescriptorFirstChar - the first char of the field type descriptor
        cpIdx - the constant pool index
        Returns:
        the field constant pool value
        Throws:
        Classfile.ClassfileFormatException - If a problem occurs.
        java.io.IOException - If an IO exception occurs.
      • readAnnotation

        private AnnotationInfo readAnnotation()
                                       throws java.io.IOException
        Read annotation entry from classfile.
        Returns:
        the annotation, as an AnnotationInfo object.
        Throws:
        java.io.IOException - If an IO exception occurs.
      • readAnnotationElementValue

        private java.lang.Object readAnnotationElementValue()
                                                     throws java.io.IOException
        Read annotation element value from classfile.
        Returns:
        the annotation element value
        Throws:
        java.io.IOException - If an IO exception occurs.
      • readTypePath

        private java.util.List<Classfile.TypePathNode> readTypePath()
                                                             throws java.io.IOException
        Throws:
        java.io.IOException
      • readConstantPoolEntries

        private void readConstantPoolEntries​(LogNode log)
                                      throws java.io.IOException
        Read constant pool entries.
        Parameters:
        log - The log
        Throws:
        java.io.IOException - Signals that an I/O exception has occurred.
      • readInterfaces

        private void readInterfaces()
                             throws java.io.IOException
        Read the class' interfaces.
        Throws:
        java.io.IOException - if an I/O exception occurs.