0
# Reflection and Descriptors
1
2
Comprehensive reflection API for runtime introspection of protocol buffer types, enabling dynamic message handling, tooling, and runtime type discovery without generated classes.
3
4
## Capabilities
5
6
### File Descriptors
7
8
Describes a complete .proto file and its contents, including all message types, enums, services, and extensions defined within it.
9
10
```java { .api }
11
/**
12
* Describes a .proto file and its contents
13
*/
14
public static class Descriptors.FileDescriptor {
15
// Basic information
16
/** Get the file name */
17
public String getName();
18
19
/** Get the proto package name */
20
public String getPackage();
21
22
/** Get file syntax (proto2 or proto3) */
23
public Syntax getSyntax();
24
25
/** Get file options */
26
public DescriptorProtos.FileOptions getOptions();
27
28
// Type discovery
29
/** Get all message types defined in this file */
30
public List<Descriptor> getMessageTypes();
31
32
/** Get all enum types defined in this file */
33
public List<EnumDescriptor> getEnumTypes();
34
35
/** Get all services defined in this file */
36
public List<ServiceDescriptor> getServices();
37
38
/** Get all extensions defined in this file */
39
public List<FieldDescriptor> getExtensions();
40
41
// Dependencies
42
/** Get files this file depends on */
43
public List<FileDescriptor> getDependencies();
44
45
/** Get public dependencies */
46
public List<FileDescriptor> getPublicDependencies();
47
48
// Lookup methods
49
/** Find message type by name within this file */
50
public Descriptor findMessageTypeByName(String name);
51
52
/** Find enum type by name within this file */
53
public EnumDescriptor findEnumTypeByName(String name);
54
55
/** Find service by name within this file */
56
public ServiceDescriptor findServiceByName(String name);
57
58
/** Find extension by name within this file */
59
public FieldDescriptor findExtensionByName(String name);
60
61
// Building file descriptors
62
/** Build from descriptor proto with dependencies */
63
public static FileDescriptor buildFrom(DescriptorProtos.FileDescriptorProto proto,
64
FileDescriptor[] dependencies)
65
throws DescriptorValidationException;
66
67
/** Build from descriptor proto with dependencies and allow unknown dependencies */
68
public static FileDescriptor buildFrom(DescriptorProtos.FileDescriptorProto proto,
69
FileDescriptor[] dependencies,
70
boolean allowUnknownDependencies)
71
throws DescriptorValidationException;
72
73
/** Convert to descriptor proto */
74
public DescriptorProtos.FileDescriptorProto toProto();
75
}
76
```
77
78
### Message Descriptors
79
80
Describes a protocol buffer message type, including all its fields, nested types, and metadata.
81
82
```java { .api }
83
/**
84
* Describes a protocol buffer message type
85
*/
86
public static class Descriptors.Descriptor implements GenericDescriptor {
87
// Basic information
88
/** Get message type name */
89
public String getName();
90
91
/** Get fully qualified message name */
92
public String getFullName();
93
94
/** Get containing file descriptor */
95
public FileDescriptor getFile();
96
97
/** Get containing message type (for nested messages) */
98
public Descriptor getContainingType();
99
100
/** Get message options */
101
public DescriptorProtos.MessageOptions getOptions();
102
103
// Field access
104
/** Get all fields in this message */
105
public List<FieldDescriptor> getFields();
106
107
/** Get all oneof groups in this message */
108
public List<OneofDescriptor> getOneofs();
109
110
/** Get all extensions that can extend this message */
111
public List<FieldDescriptor> getExtensions();
112
113
// Nested type access
114
/** Get all nested message types */
115
public List<Descriptor> getNestedTypes();
116
117
/** Get all nested enum types */
118
public List<EnumDescriptor> getEnumTypes();
119
120
// Capability queries
121
/** Check if this message type is extendable */
122
public boolean isExtendable();
123
124
/** Check if this is a map entry message */
125
public boolean isMapEntry();
126
127
// Field lookup methods
128
/** Find field by name */
129
public FieldDescriptor findFieldByName(String name);
130
131
/** Find field by field number */
132
public FieldDescriptor findFieldByNumber(int number);
133
134
/** Find nested message type by name */
135
public Descriptor findNestedTypeByName(String name);
136
137
/** Find nested enum type by name */
138
public EnumDescriptor findEnumTypeByName(String name);
139
140
// Proto conversion
141
/** Convert to descriptor proto */
142
public DescriptorProtos.DescriptorProto toProto();
143
}
144
```
145
146
### Field Descriptors
147
148
Describes individual fields within protocol buffer messages, including type information, constraints, and metadata.
149
150
```java { .api }
151
/**
152
* Describes a field within a message
153
*/
154
public static class Descriptors.FieldDescriptor implements GenericDescriptor, Comparable<FieldDescriptor> {
155
// Basic information
156
/** Get field name */
157
public String getName();
158
159
/** Get field number */
160
public int getNumber();
161
162
/** Get fully qualified field name */
163
public String getFullName();
164
165
/** Get JSON field name */
166
public String getJsonName();
167
168
/** Get field options */
169
public DescriptorProtos.FieldOptions getOptions();
170
171
// Type information
172
/** Get protocol buffer field type */
173
public Type getType();
174
175
/** Get corresponding Java type */
176
public JavaType getJavaType();
177
178
/** Get wire format type */
179
public WireFormat.FieldType getLiteType();
180
181
// Cardinality and constraints
182
/** Check if field is required (proto2) */
183
public boolean isRequired();
184
185
/** Check if field is optional */
186
public boolean isOptional();
187
188
/** Check if field is repeated */
189
public boolean isRepeated();
190
191
/** Check if repeated field is packed */
192
public boolean isPacked();
193
194
/** Check if field is a map field */
195
public boolean isMapField();
196
197
/** Check if field is an extension field */
198
public boolean isExtension();
199
200
// Default values
201
/** Check if field has explicit default value */
202
public boolean hasDefaultValue();
203
204
/** Get default value for this field */
205
public Object getDefaultValue();
206
207
// Containing types
208
/** Get message type that contains this field */
209
public Descriptor getContainingType();
210
211
/** Get containing oneof group (if part of oneof) */
212
public OneofDescriptor getContainingOneof();
213
214
/** Get extension scope (for extension fields) */
215
public Descriptor getExtensionScope();
216
217
// Referenced types
218
/** Get message type (for message fields) */
219
public Descriptor getMessageType();
220
221
/** Get enum type (for enum fields) */
222
public EnumDescriptor getEnumType();
223
224
// Proto conversion
225
/** Convert to field descriptor proto */
226
public DescriptorProtos.FieldDescriptorProto toProto();
227
228
// Field type enumeration
229
public enum Type {
230
DOUBLE, FLOAT, INT64, UINT64, INT32, FIXED64, FIXED32,
231
BOOL, STRING, GROUP, MESSAGE, BYTES, UINT32, ENUM,
232
SFIXED32, SFIXED64, SINT32, SINT64;
233
234
public JavaType getJavaType();
235
public WireFormat.FieldType getLiteType();
236
}
237
238
public enum JavaType {
239
INT, LONG, FLOAT, DOUBLE, BOOLEAN, STRING, BYTE_STRING, ENUM, MESSAGE;
240
241
public Object getDefaultDefault();
242
}
243
}
244
```
245
246
### Enum Descriptors
247
248
Describes protocol buffer enum types and their values.
249
250
```java { .api }
251
/**
252
* Describes an enum type
253
*/
254
public static class Descriptors.EnumDescriptor implements GenericDescriptor {
255
// Basic information
256
/** Get enum name */
257
public String getName();
258
259
/** Get fully qualified enum name */
260
public String getFullName();
261
262
/** Get containing file */
263
public FileDescriptor getFile();
264
265
/** Get containing message type (for nested enums) */
266
public Descriptor getContainingType();
267
268
/** Get enum options */
269
public DescriptorProtos.EnumOptions getOptions();
270
271
// Value access
272
/** Get all enum values */
273
public List<EnumValueDescriptor> getValues();
274
275
/** Find enum value by name */
276
public EnumValueDescriptor findValueByName(String name);
277
278
/** Find enum value by number */
279
public EnumValueDescriptor findValueByNumber(int number);
280
281
// Proto conversion
282
/** Convert to enum descriptor proto */
283
public DescriptorProtos.EnumDescriptorProto toProto();
284
}
285
286
/**
287
* Describes an enum value
288
*/
289
public static class Descriptors.EnumValueDescriptor implements GenericDescriptor {
290
// Basic information
291
/** Get enum value name */
292
public String getName();
293
294
/** Get enum value number */
295
public int getNumber();
296
297
/** Get fully qualified name */
298
public String getFullName();
299
300
/** Get containing enum type */
301
public EnumDescriptor getType();
302
303
/** Get value options */
304
public DescriptorProtos.EnumValueOptions getOptions();
305
306
/** Convert to enum value descriptor proto */
307
public DescriptorProtos.EnumValueDescriptorProto toProto();
308
}
309
```
310
311
### Service Descriptors
312
313
Describes protocol buffer services and their methods (used with RPC frameworks).
314
315
```java { .api }
316
/**
317
* Describes a service
318
*/
319
public static class Descriptors.ServiceDescriptor implements GenericDescriptor {
320
// Basic information
321
/** Get service name */
322
public String getName();
323
324
/** Get fully qualified service name */
325
public String getFullName();
326
327
/** Get containing file */
328
public FileDescriptor getFile();
329
330
/** Get service options */
331
public DescriptorProtos.ServiceOptions getOptions();
332
333
// Method access
334
/** Get all methods in this service */
335
public List<MethodDescriptor> getMethods();
336
337
/** Find method by name */
338
public MethodDescriptor findMethodByName(String name);
339
340
/** Convert to service descriptor proto */
341
public DescriptorProtos.ServiceDescriptorProto toProto();
342
}
343
344
/**
345
* Describes a service method
346
*/
347
public static class Descriptors.MethodDescriptor implements GenericDescriptor {
348
// Basic information
349
/** Get method name */
350
public String getName();
351
352
/** Get fully qualified method name */
353
public String getFullName();
354
355
/** Get containing service */
356
public ServiceDescriptor getService();
357
358
/** Get method options */
359
public DescriptorProtos.MethodOptions getOptions();
360
361
// Input/output types
362
/** Get input message type */
363
public Descriptor getInputType();
364
365
/** Get output message type */
366
public Descriptor getOutputType();
367
368
// Streaming information
369
/** Check if client streaming */
370
public boolean isClientStreaming();
371
372
/** Check if server streaming */
373
public boolean isServerStreaming();
374
375
/** Convert to method descriptor proto */
376
public DescriptorProtos.MethodDescriptorProto toProto();
377
}
378
```
379
380
### Oneof Descriptors
381
382
Describes oneof field groups within messages.
383
384
```java { .api }
385
/**
386
* Describes a oneof field group
387
*/
388
public static class Descriptors.OneofDescriptor implements GenericDescriptor {
389
// Basic information
390
/** Get oneof name */
391
public String getName();
392
393
/** Get fully qualified oneof name */
394
public String getFullName();
395
396
/** Get containing message type */
397
public Descriptor getContainingType();
398
399
/** Get oneof options */
400
public DescriptorProtos.OneofOptions getOptions();
401
402
// Field access
403
/** Get all fields in this oneof group */
404
public List<FieldDescriptor> getFields();
405
406
/** Get field by index */
407
public FieldDescriptor getField(int index);
408
409
/** Get number of fields in oneof */
410
public int getFieldCount();
411
412
/** Check if oneof is synthetic (proto3 optional) */
413
public boolean isSynthetic();
414
415
/** Convert to oneof descriptor proto */
416
public DescriptorProtos.OneofDescriptorProto toProto();
417
}
418
```
419
420
### Type Registry
421
422
Registry for resolving Any message types by type URL.
423
424
```java { .api }
425
/**
426
* Registry for resolving Any message types
427
*/
428
public class TypeRegistry {
429
// Static factory methods
430
/** Get empty type registry */
431
public static TypeRegistry getEmptyTypeRegistry();
432
433
/** Create new builder */
434
public static Builder newBuilder();
435
436
// Type resolution
437
/** Find type by full name */
438
public Descriptor find(String name);
439
440
/** Find type by type URL */
441
public Descriptor getDescriptorForTypeUrl(String typeUrl);
442
443
/**
444
* Builder for constructing type registries
445
*/
446
public static class Builder {
447
/** Add message type and all its dependencies */
448
public Builder add(Descriptor messageType);
449
450
/** Add multiple message types */
451
public Builder add(Iterable<Descriptor> messageTypes);
452
453
/** Build the type registry */
454
public TypeRegistry build();
455
}
456
}
457
```
458
459
### Descriptor Validation
460
461
Exception handling for descriptor validation errors.
462
463
```java { .api }
464
/**
465
* Exception thrown when descriptor validation fails
466
*/
467
public static class Descriptors.DescriptorValidationException extends Exception {
468
/** Create with description */
469
public DescriptorValidationException(GenericDescriptor problemDescriptor, String description);
470
471
/** Create with description and cause */
472
public DescriptorValidationException(GenericDescriptor problemDescriptor, String description, Throwable cause);
473
474
/** Get descriptor that caused the problem */
475
public GenericDescriptor getProblemDescriptor();
476
477
/** Get problem description */
478
public String getProblemDescription();
479
}
480
481
/**
482
* Base interface for all descriptor types
483
*/
484
public interface GenericDescriptor {
485
/** Get name of this descriptor */
486
String getName();
487
488
/** Get fully qualified name */
489
String getFullName();
490
491
/** Get containing file */
492
FileDescriptor getFile();
493
}
494
```
495
496
**Usage Examples:**
497
498
```java
499
import com.google.protobuf.Descriptors;
500
import com.google.protobuf.TypeRegistry;
501
502
// Working with file descriptors
503
FileDescriptor fileDesc = MyMessage.getDescriptor().getFile();
504
System.out.println("File: " + fileDesc.getName());
505
System.out.println("Package: " + fileDesc.getPackage());
506
507
// Exploring message structure
508
Descriptor messageDesc = MyMessage.getDescriptor();
509
System.out.println("Message: " + messageDesc.getFullName());
510
511
for (FieldDescriptor field : messageDesc.getFields()) {
512
System.out.printf("Field %d: %s (%s)%n",
513
field.getNumber(), field.getName(), field.getType());
514
515
if (field.isRepeated()) {
516
System.out.println(" - Repeated field");
517
}
518
519
if (field.getType() == FieldDescriptor.Type.MESSAGE) {
520
System.out.println(" - Message type: " + field.getMessageType().getFullName());
521
}
522
523
if (field.getContainingOneof() != null) {
524
System.out.println(" - Part of oneof: " + field.getContainingOneof().getName());
525
}
526
}
527
528
// Working with enums
529
for (EnumDescriptor enumDesc : messageDesc.getEnumTypes()) {
530
System.out.println("Enum: " + enumDesc.getName());
531
for (EnumValueDescriptor value : enumDesc.getValues()) {
532
System.out.printf(" %s = %d%n", value.getName(), value.getNumber());
533
}
534
}
535
536
// Building type registry for Any messages
537
TypeRegistry typeRegistry = TypeRegistry.newBuilder()
538
.add(MyMessage.getDescriptor())
539
.add(AnotherMessage.getDescriptor())
540
.build();
541
542
// Find types at runtime
543
Descriptor foundType = typeRegistry.find("com.example.MyMessage");
544
if (foundType != null) {
545
System.out.println("Found type: " + foundType.getFullName());
546
}
547
```
548
549
### Dynamic Message Creation
550
551
Creating and manipulating messages using descriptors without generated classes.
552
553
```java { .api }
554
/**
555
* Dynamic message creation and manipulation using descriptors
556
*/
557
558
// Example: Creating dynamic messages
559
Descriptor messageType = getMessageDescriptor(); // Get from somewhere
560
DynamicMessage.Builder builder = DynamicMessage.newBuilder(messageType);
561
562
// Set fields by descriptor
563
FieldDescriptor nameField = messageType.findFieldByName("name");
564
FieldDescriptor ageField = messageType.findFieldByName("age");
565
566
builder.setField(nameField, "John Doe");
567
builder.setField(ageField, 30);
568
569
DynamicMessage message = builder.build();
570
571
// Read fields by descriptor
572
String name = (String) message.getField(nameField);
573
Integer age = (Integer) message.getField(ageField);
574
575
// Work with repeated fields
576
FieldDescriptor listField = messageType.findFieldByName("items");
577
if (listField.isRepeated()) {
578
builder.addRepeatedField(listField, "item1");
579
builder.addRepeatedField(listField, "item2");
580
581
DynamicMessage messageWithList = builder.build();
582
int count = messageWithList.getRepeatedFieldCount(listField);
583
for (int i = 0; i < count; i++) {
584
String item = (String) messageWithList.getRepeatedField(listField, i);
585
System.out.println("Item " + i + ": " + item);
586
}
587
}
588
```
589
590
## Exception Handling
591
592
Common exceptions when working with descriptors:
593
594
- **DescriptorValidationException**: Thrown when building descriptors from invalid proto definitions
595
- **IllegalArgumentException**: Thrown for invalid field numbers, unknown field names, or type mismatches
596
- **NullPointerException**: Thrown when required parameters are null
597
598
## Types
599
600
```java { .api }
601
// Core descriptor interfaces
602
public interface GenericDescriptor {
603
String getName();
604
String getFullName();
605
FileDescriptor getFile();
606
}
607
608
// Syntax enumeration for proto files
609
public enum Syntax {
610
PROTO2, PROTO3
611
}
612
613
// Descriptor protocol buffer definitions (from descriptor.proto)
614
// These are the underlying proto definitions used to build descriptors
615
public class DescriptorProtos {
616
public static class FileDescriptorProto extends GeneratedMessage { /* ... */ }
617
public static class DescriptorProto extends GeneratedMessage { /* ... */ }
618
public static class FieldDescriptorProto extends GeneratedMessage { /* ... */ }
619
public static class EnumDescriptorProto extends GeneratedMessage { /* ... */ }
620
public static class EnumValueDescriptorProto extends GeneratedMessage { /* ... */ }
621
public static class ServiceDescriptorProto extends GeneratedMessage { /* ... */ }
622
public static class MethodDescriptorProto extends GeneratedMessage { /* ... */ }
623
public static class OneofDescriptorProto extends GeneratedMessage { /* ... */ }
624
625
// Options messages for customizing behavior
626
public static class FileOptions extends GeneratedMessage { /* ... */ }
627
public static class MessageOptions extends GeneratedMessage { /* ... */ }
628
public static class FieldOptions extends GeneratedMessage { /* ... */ }
629
public static class EnumOptions extends GeneratedMessage { /* ... */ }
630
public static class EnumValueOptions extends GeneratedMessage { /* ... */ }
631
public static class ServiceOptions extends GeneratedMessage { /* ... */ }
632
public static class MethodOptions extends GeneratedMessage { /* ... */ }
633
public static class OneofOptions extends GeneratedMessage { /* ... */ }
634
}
635
```