0
# Class Metadata
1
2
The ClassGraph library provides comprehensive metadata about classes through the ClassInfo hierarchy. This includes detailed information about classes, methods, fields, annotations, and their relationships.
3
4
## ClassInfo - Core Class Metadata
5
6
```java { .api }
7
import io.github.classgraph.ClassInfo;
8
import io.github.classgraph.MethodInfo;
9
import io.github.classgraph.FieldInfo;
10
import io.github.classgraph.AnnotationInfo;
11
import io.github.classgraph.ClassTypeSignature;
12
import io.github.classgraph.PackageInfo;
13
import io.github.classgraph.ModuleInfo;
14
import java.util.List;
15
```
16
17
### Basic Class Information
18
19
```java { .api }
20
// Get ClassInfo from ScanResult
21
ClassInfo classInfo = scanResult.getClassInfo("com.example.MyClass");
22
23
if (classInfo != null) {
24
// Basic naming and location
25
String name = classInfo.getName(); // "com.example.MyClass"
26
String simpleName = classInfo.getSimpleName(); // "MyClass"
27
String packageName = classInfo.getPackageName(); // "com.example"
28
29
// Container information
30
PackageInfo packageInfo = classInfo.getPackageInfo();
31
ModuleInfo moduleInfo = classInfo.getModuleInfo(); // null if not in module
32
33
// External class flag
34
boolean isExternal = classInfo.isExternalClass(); // true if outside scan scope
35
}
36
```
37
38
### Classfile and Source Information
39
40
```java { .api }
41
// Classfile version information
42
int majorVersion = classInfo.getClassfileMajorVersion(); // e.g., 55 for Java 11
43
int minorVersion = classInfo.getClassfileMinorVersion(); // Usually 0
44
45
// Source file information
46
String sourceFile = classInfo.getSourceFile(); // e.g., "MyClass.java"
47
```
48
49
### Modifiers and Type Classification
50
51
```java { .api }
52
// Access modifiers
53
int modifiers = classInfo.getModifiers();
54
String modifiersStr = classInfo.getModifiersStr(); // "public final"
55
56
// Visibility checks
57
boolean isPublic = classInfo.isPublic();
58
boolean isPrivate = classInfo.isPrivate();
59
boolean isProtected = classInfo.isProtected();
60
boolean isPackageVisible = classInfo.isPackageVisible();
61
62
// Modifier checks
63
boolean isAbstract = classInfo.isAbstract();
64
boolean isFinal = classInfo.isFinal();
65
boolean isStatic = classInfo.isStatic();
66
boolean isSynthetic = classInfo.isSynthetic();
67
68
// Type classification
69
boolean isInterface = classInfo.isInterface();
70
boolean isAnnotation = classInfo.isAnnotation();
71
boolean isEnum = classInfo.isEnum();
72
boolean isRecord = classInfo.isRecord(); // JDK 14+
73
boolean isStandardClass = classInfo.isStandardClass(); // Not interface/annotation/enum
74
boolean isArrayClass = classInfo.isArrayClass();
75
76
// Class nesting
77
boolean isInnerClass = classInfo.isInnerClass();
78
boolean isOuterClass = classInfo.isOuterClass();
79
boolean isAnonymousInnerClass = classInfo.isAnonymousInnerClass();
80
```
81
82
### Class Relationship Checks
83
84
```java { .api }
85
// Inheritance checks
86
boolean extendsClass = classInfo.extendsSuperclass("java.util.AbstractList");
87
boolean extendsByClass = classInfo.extendsSuperclass(AbstractList.class);
88
89
// Interface implementation checks
90
boolean implementsInterface = classInfo.implementsInterface("java.util.List");
91
boolean implementsByClass = classInfo.implementsInterface(List.class);
92
93
// Annotation checks
94
boolean hasAnnotation = classInfo.hasAnnotation("javax.persistence.Entity");
95
boolean hasAnnotationByClass = classInfo.hasAnnotation(Entity.class);
96
```
97
98
### Class Hierarchy Information
99
100
```java { .api }
101
// Superclass hierarchy
102
ClassInfo superclass = classInfo.getSuperclass(); // Direct superclass
103
ClassInfoList superclasses = classInfo.getSuperclasses(); // Full hierarchy
104
105
// Subclass relationships
106
ClassInfoList subclasses = classInfo.getSubclasses(); // Direct and indirect
107
108
// Interface relationships
109
ClassInfoList interfaces = classInfo.getInterfaces(); // Implemented interfaces
110
ClassInfoList implementingClasses = classInfo.getClassesImplementing(); // Classes implementing this interface (if interface)
111
112
// Inner/outer class relationships
113
ClassInfoList innerClasses = classInfo.getInnerClasses();
114
ClassInfoList outerClasses = classInfo.getOuterClasses();
115
```
116
117
## Field Information
118
119
### Field Discovery and Access
120
121
```java { .api }
122
// Check for field existence
123
boolean hasDeclaredField = classInfo.hasDeclaredField("userName");
124
boolean hasField = classInfo.hasField("userName"); // Including inherited
125
126
// Get field information
127
FieldInfo declaredField = classInfo.getDeclaredFieldInfo("userName");
128
FieldInfo field = classInfo.getFieldInfo("userName"); // Including inherited
129
130
// Get all fields
131
FieldInfoList declaredFields = classInfo.getDeclaredFieldInfo();
132
FieldInfoList allFields = classInfo.getFieldInfo(); // Including inherited
133
134
// Enum-specific field access
135
if (classInfo.isEnum()) {
136
FieldInfoList enumConstants = classInfo.getEnumConstants();
137
List<Object> enumConstantObjects = classInfo.getEnumConstantObjects();
138
}
139
```
140
141
### Field Annotation Queries
142
143
```java { .api }
144
// Check for field annotations
145
boolean hasDeclaredFieldAnnotation = classInfo.hasDeclaredFieldAnnotation("javax.persistence.Column");
146
boolean hasFieldAnnotation = classInfo.hasFieldAnnotation("javax.persistence.Column"); // Including inherited
147
148
// Field annotation with class types
149
boolean hasColumnAnnotation = classInfo.hasFieldAnnotation(Column.class);
150
```
151
152
### FieldInfo Details
153
154
```java { .api }
155
FieldInfo fieldInfo = classInfo.getDeclaredFieldInfo("userName");
156
157
if (fieldInfo != null) {
158
// Basic field information
159
String name = fieldInfo.getName();
160
String className = fieldInfo.getClassName();
161
ClassInfo fieldClassInfo = fieldInfo.getClassInfo();
162
163
// Modifiers
164
int modifiers = fieldInfo.getModifiers();
165
String modifiersStr = fieldInfo.getModifiersStr();
166
boolean isTransient = fieldInfo.isTransient();
167
boolean isEnum = fieldInfo.isEnum();
168
169
// Type information
170
TypeSignature typeDescriptor = fieldInfo.getTypeDescriptor();
171
TypeSignature typeSignature = fieldInfo.getTypeSignature(); // Generic signature
172
TypeSignature typeSignatureOrDescriptor = fieldInfo.getTypeSignatureOrTypeDescriptor();
173
174
// Constant value (for static final fields)
175
Object constantValue = fieldInfo.getConstantInitializerValue();
176
177
// Annotation information
178
AnnotationInfoList annotations = fieldInfo.getAnnotationInfo();
179
180
// Load actual Field via reflection
181
Field reflectionField = fieldInfo.loadClassAndGetField();
182
}
183
```
184
185
## Method Information
186
187
### Method Discovery and Access
188
189
```java { .api }
190
// Check for method existence
191
boolean hasDeclaredMethod = classInfo.hasDeclaredMethod("getUserName");
192
boolean hasMethod = classInfo.hasMethod("getUserName"); // Including inherited
193
194
// Get methods by name
195
MethodInfoList declaredMethods = classInfo.getDeclaredMethodInfo("getUserName");
196
MethodInfoList methods = classInfo.getMethodInfo("getUserName"); // Including inherited
197
198
// Get all methods
199
MethodInfoList allDeclaredMethods = classInfo.getDeclaredMethodInfo();
200
MethodInfoList allMethods = classInfo.getMethodInfo(); // Including inherited
201
202
// Constructor access
203
MethodInfoList declaredConstructors = classInfo.getDeclaredConstructorInfo();
204
MethodInfoList constructors = classInfo.getConstructorInfo();
205
206
// Combined method and constructor access
207
MethodInfoList allDeclaredMethodsAndConstructors = classInfo.getDeclaredMethodAndConstructorInfo();
208
MethodInfoList allMethodsAndConstructors = classInfo.getMethodAndConstructorInfo();
209
```
210
211
### Method Annotation Queries
212
213
```java { .api }
214
// Check for method annotations
215
boolean hasDeclaredMethodAnnotation = classInfo.hasDeclaredMethodAnnotation("org.junit.Test");
216
boolean hasMethodAnnotation = classInfo.hasMethodAnnotation("org.junit.Test"); // Including inherited
217
218
// Parameter annotation checks
219
boolean hasDeclaredParamAnnotation = classInfo.hasDeclaredMethodParameterAnnotation("javax.validation.Valid");
220
boolean hasParamAnnotation = classInfo.hasMethodParameterAnnotation("javax.validation.Valid"); // Including inherited
221
```
222
223
### MethodInfo Details
224
225
```java { .api }
226
MethodInfo methodInfo = classInfo.getDeclaredMethodInfo("processUser").get(0);
227
228
if (methodInfo != null) {
229
// Basic method information
230
String name = methodInfo.getName();
231
String className = methodInfo.getClassName();
232
ClassInfo methodClassInfo = methodInfo.getClassInfo();
233
234
// Modifiers
235
int modifiers = methodInfo.getModifiers();
236
String modifiersStr = methodInfo.getModifiersStr();
237
238
// Method type checks
239
boolean isConstructor = methodInfo.isConstructor();
240
boolean isSynchronized = methodInfo.isSynchronized();
241
boolean isBridge = methodInfo.isBridge();
242
boolean isVarArgs = methodInfo.isVarArgs();
243
boolean isNative = methodInfo.isNative();
244
boolean isAbstract = methodInfo.isAbstract();
245
boolean isStrict = methodInfo.isStrict();
246
boolean hasBody = methodInfo.hasBody();
247
boolean isDefault = methodInfo.isDefault(); // Default interface method
248
249
// Type signatures
250
MethodTypeSignature typeDescriptor = methodInfo.getTypeDescriptor();
251
MethodTypeSignature typeSignature = methodInfo.getTypeSignature();
252
MethodTypeSignature typeSignatureOrDescriptor = methodInfo.getTypeSignatureOrTypeDescriptor();
253
254
// Exception information
255
ClassInfoList thrownExceptions = methodInfo.getThrownExceptions();
256
String[] thrownExceptionNames = methodInfo.getThrownExceptionNames();
257
258
// Debug information
259
int minLineNum = methodInfo.getMinLineNum();
260
int maxLineNum = methodInfo.getMaxLineNum();
261
262
// Parameter information
263
MethodParameterInfo[] parameters = methodInfo.getParameterInfo();
264
boolean hasParamAnnotation = methodInfo.hasParameterAnnotation(Valid.class);
265
266
// Annotation information
267
AnnotationInfoList annotations = methodInfo.getAnnotationInfo();
268
269
// Load actual Method via reflection
270
Method reflectionMethod = methodInfo.loadClassAndGetMethod();
271
}
272
```
273
274
### Method Parameter Information
275
276
```java { .api }
277
MethodParameterInfo[] parameters = methodInfo.getParameterInfo();
278
279
for (MethodParameterInfo param : parameters) {
280
// Basic parameter info
281
MethodInfo containingMethod = param.getMethodInfo();
282
String paramName = param.getName(); // May be null if not available
283
284
// Parameter modifiers
285
int modifiers = param.getModifiers();
286
String modifiersStr = param.getModifiersStr();
287
288
// Type information
289
TypeSignature typeSignature = param.getTypeSignature();
290
TypeSignature typeDescriptor = param.getTypeDescriptor();
291
TypeSignature typeSignatureOrDescriptor = param.getTypeSignatureOrTypeDescriptor();
292
293
// Parameter annotations
294
AnnotationInfoList annotations = param.getAnnotationInfo();
295
AnnotationInfo validAnnotation = param.getAnnotationInfo(Valid.class);
296
}
297
```
298
299
## Annotation Information
300
301
### Class Annotations
302
303
```java { .api }
304
// Get all annotations on a class
305
AnnotationInfoList classAnnotations = classInfo.getAnnotationInfo();
306
307
// Get specific annotation
308
AnnotationInfo entityAnnotation = classInfo.getAnnotationInfo("javax.persistence.Entity");
309
AnnotationInfo entityByClass = classInfo.getAnnotationInfo(Entity.class);
310
311
// Repeatable annotations (Java 8+)
312
AnnotationInfoList repeatableAnnotations = classInfo.getAnnotationInfoRepeatable(Repeatable.class);
313
314
// Default annotation parameter values
315
AnnotationParameterValueList defaults = classInfo.getAnnotationDefaultParameterValues();
316
317
// Get classes annotated with this annotation (if this class is an annotation)
318
ClassInfoList annotatedClasses = classInfo.getClassesWithAnnotation();
319
```
320
321
### AnnotationInfo Details
322
323
```java { .api }
324
AnnotationInfo annotation = classInfo.getAnnotationInfo(Entity.class);
325
326
if (annotation != null) {
327
// Basic annotation information
328
String name = annotation.getName();
329
boolean isInherited = annotation.isInherited();
330
331
// Parameter values
332
AnnotationParameterValueList defaultValues = annotation.getDefaultParameterValues();
333
AnnotationParameterValueList actualValues = annotation.getParameterValues();
334
AnnotationParameterValueList allValues = annotation.getParameterValues(true); // Including defaults
335
336
// Get related class information
337
ClassInfo annotationClassInfo = annotation.getClassInfo();
338
339
// Load and instantiate annotation
340
Annotation annotationInstance = annotation.loadClassAndInstantiate();
341
}
342
```
343
344
### Annotation Parameter Values
345
346
```java { .api }
347
AnnotationParameterValueList paramValues = annotation.getParameterValues();
348
349
for (AnnotationParameterValue param : paramValues) {
350
String paramName = param.getName();
351
Object value = param.getValue();
352
353
// Value can be various types:
354
// - String, primitive types, Class references
355
// - Arrays of the above
356
// - Nested annotations (AnnotationInfo)
357
// - Enum values (AnnotationEnumValue)
358
359
if (value instanceof String) {
360
String stringValue = (String) value;
361
} else if (value instanceof AnnotationEnumValue) {
362
AnnotationEnumValue enumValue = (AnnotationEnumValue) value;
363
String enumClassName = enumValue.getClassName();
364
String enumConstantName = enumValue.getValueName();
365
Object actualEnumValue = enumValue.loadClassAndReturnEnumValue();
366
} else if (value instanceof AnnotationInfo) {
367
AnnotationInfo nestedAnnotation = (AnnotationInfo) value;
368
// Process nested annotation...
369
}
370
}
371
372
// Direct parameter value access
373
Object tableNameValue = paramValues.getValue("name");
374
```
375
376
## Type Signatures and Generics
377
378
ClassInfo provides access to complete generic type information:
379
380
```java { .api }
381
// Get type signature information
382
String typeSignatureStr = classInfo.getTypeSignatureStr();
383
ClassTypeSignature typeSignature = classInfo.getTypeSignature();
384
ClassTypeSignature typeSignatureOrDescriptor = classInfo.getTypeSignatureOrTypeDescriptor();
385
ClassTypeSignature typeDescriptor = classInfo.getTypeDescriptor(); // Synthetic descriptor
386
387
if (typeSignature != null) {
388
// Generic type parameters
389
List<TypeParameter> typeParameters = typeSignature.getTypeParameters();
390
391
// Superclass with generics
392
ClassRefTypeSignature superclassSignature = typeSignature.getSuperclassSignature();
393
394
// Implemented interfaces with generics
395
List<ClassRefTypeSignature> superinterfaceSignatures = typeSignature.getSuperinterfaceSignatures();
396
}
397
```
398
399
## Location and Resources
400
401
### Classpath Element Information
402
403
```java { .api }
404
// Get classpath element containing this class
405
URI classpathElementURI = classInfo.getClasspathElementURI();
406
URL classpathElementURL = classInfo.getClasspathElementURL();
407
File classpathElementFile = classInfo.getClasspathElementFile();
408
409
// Module information (if applicable)
410
ModuleRef moduleRef = classInfo.getModuleRef();
411
412
// Get the resource for the class file itself
413
Resource classResource = classInfo.getResource();
414
```
415
416
## Class Loading
417
418
### Safe Class Loading
419
420
```java { .api }
421
// Load class with error handling
422
try {
423
Class<?> clazz = classInfo.loadClass(false); // false = don't initialize
424
System.out.println("Loaded: " + clazz.getName());
425
} catch (Exception e) {
426
System.err.println("Failed to load class: " + e.getMessage());
427
}
428
429
// Load without error handling (throws on failure)
430
Class<?> clazz = classInfo.loadClass();
431
432
// Load and cast with type safety
433
Class<? extends Service> serviceClass = classInfo.loadClass(Service.class, false);
434
Class<? extends Service> serviceClassThrow = classInfo.loadClass(Service.class); // Throws on error
435
```
436
437
## Practical Examples
438
439
### Find Service Implementations with Configuration
440
441
```java { .api }
442
ClassInfoList serviceImpls = scanResult.getClassesImplementing("com.example.Service");
443
444
for (ClassInfo serviceClass : serviceImpls) {
445
// Check if it's a concrete implementation
446
if (!serviceClass.isAbstract() && !serviceClass.isInterface()) {
447
System.out.println("Service Implementation: " + serviceClass.getName());
448
449
// Check for configuration annotations
450
AnnotationInfo configAnnotation = serviceClass.getAnnotationInfo("com.example.Configuration");
451
if (configAnnotation != null) {
452
String configName = (String) configAnnotation.getParameterValues().getValue("name");
453
System.out.println(" Configuration: " + configName);
454
}
455
456
// Check for required dependencies via constructor parameters
457
MethodInfoList constructors = serviceClass.getDeclaredConstructorInfo();
458
for (MethodInfo constructor : constructors) {
459
if (constructor.isPublic()) {
460
MethodParameterInfo[] params = constructor.getParameterInfo();
461
System.out.println(" Constructor dependencies:");
462
for (MethodParameterInfo param : params) {
463
TypeSignature paramType = param.getTypeSignature();
464
System.out.println(" " + paramType.toString());
465
}
466
}
467
}
468
}
469
}
470
```
471
472
### Analyze REST Controller Methods
473
474
```java { .api }
475
ClassInfoList controllers = scanResult.getClassesWithAnnotation("org.springframework.web.bind.annotation.RestController");
476
477
for (ClassInfo controller : controllers) {
478
System.out.println("Controller: " + controller.getName());
479
480
// Find request mapping methods
481
MethodInfoList requestMethods = controller.getDeclaredMethodInfo()
482
.filter(method ->
483
method.hasAnnotation("org.springframework.web.bind.annotation.GetMapping") ||
484
method.hasAnnotation("org.springframework.web.bind.annotation.PostMapping") ||
485
method.hasAnnotation("org.springframework.web.bind.annotation.PutMapping") ||
486
method.hasAnnotation("org.springframework.web.bind.annotation.DeleteMapping"));
487
488
for (MethodInfo method : requestMethods) {
489
System.out.println(" Endpoint: " + method.getName());
490
491
// Extract HTTP method and path
492
AnnotationInfo getMapping = method.getAnnotationInfo("org.springframework.web.bind.annotation.GetMapping");
493
if (getMapping != null) {
494
Object pathValue = getMapping.getParameterValues().getValue("value");
495
if (pathValue instanceof String[]) {
496
String[] paths = (String[]) pathValue;
497
System.out.println(" GET " + Arrays.toString(paths));
498
}
499
}
500
501
// Analyze parameters for validation
502
MethodParameterInfo[] params = method.getParameterInfo();
503
for (MethodParameterInfo param : params) {
504
if (param.hasAnnotation("javax.validation.Valid")) {
505
System.out.println(" Validated parameter: " + param.getTypeSignature());
506
}
507
}
508
}
509
}
510
```
511
512
The ClassInfo API provides comprehensive access to all aspects of class metadata, enabling sophisticated analysis and code generation capabilities while maintaining type safety and performance.