0
# Native Image Support
1
2
The Native Image Support capability provides registration systems for GraalVM native image compilation, including reflection and dynamic proxy support.
3
4
## Reflection Registration
5
6
### Register for Reflection Annotation
7
8
```java { .api }
9
@Retention(RetentionPolicy.RUNTIME)
10
@Target(ElementType.TYPE)
11
public @interface RegisterForReflection {
12
/**
13
* Register methods for reflection access.
14
* @return true to register methods (default: true)
15
*/
16
boolean methods() default true;
17
18
/**
19
* Register fields for reflection access.
20
* @return true to register fields (default: true)
21
*/
22
boolean fields() default true;
23
24
/**
25
* Skip nested classes during registration.
26
* @return true to ignore nested classes (default: false)
27
*/
28
boolean ignoreNested() default false;
29
30
/**
31
* Alternative target classes to register instead of annotated class.
32
* @return Array of classes to register
33
*/
34
Class<?>[] targets() default {};
35
36
/**
37
* Target class names when classes are not available at compile time.
38
* @return Array of class names to register
39
*/
40
String[] classNames() default {};
41
42
/**
43
* Register for serialization support.
44
* @return true to enable serialization support (default: false)
45
*/
46
boolean serialization() default false;
47
48
/**
49
* Register the complete class hierarchy.
50
* @return true to register full hierarchy (default: false)
51
*/
52
boolean registerFullHierarchy() default false;
53
54
/**
55
* Mark allocated instances as unsafe.
56
* @return true to mark as unsafe allocated (default: false)
57
*/
58
boolean unsafeAllocated() default false;
59
60
/**
61
* Lambda capturing types for registration.
62
* @return Array of lambda capturing type names
63
*/
64
String[] lambdaCapturingTypes() default {};
65
}
66
```
67
68
## Proxy Registration
69
70
### Register for Proxy Annotation
71
72
```java { .api }
73
@Retention(RetentionPolicy.RUNTIME)
74
@Target(ElementType.TYPE)
75
public @interface RegisterForProxy {
76
/**
77
* Interface classes to register for dynamic proxy creation.
78
* @return Array of interface classes
79
*/
80
Class<?>[] value() default {};
81
}
82
```
83
84
## Usage Examples
85
86
### Basic Reflection Registration
87
88
```java
89
import io.quarkus.runtime.annotations.RegisterForReflection;
90
91
// Register current class for reflection
92
@RegisterForReflection
93
public class MyReflectiveClass {
94
private String privateField;
95
public int publicField;
96
97
private void privateMethod() {
98
// This method will be accessible via reflection
99
}
100
101
public void publicMethod() {
102
// This method will be accessible via reflection
103
}
104
}
105
```
106
107
### Register External Classes
108
109
```java
110
import io.quarkus.runtime.annotations.RegisterForReflection;
111
import com.fasterxml.jackson.databind.ObjectMapper;
112
import java.util.HashMap;
113
import java.util.ArrayList;
114
115
// Register external classes for reflection
116
@RegisterForReflection(targets = {
117
ObjectMapper.class,
118
HashMap.class,
119
ArrayList.class
120
})
121
public class ReflectionConfig {
122
// This class serves as a configuration holder
123
}
124
```
125
126
### Register by Class Name
127
128
```java
129
import io.quarkus.runtime.annotations.RegisterForReflection;
130
131
// Register classes by name (useful when classes might not be on classpath)
132
@RegisterForReflection(classNames = {
133
"com.example.DynamicallyLoadedClass",
134
"org.external.library.SomeClass",
135
"java.util.concurrent.ThreadPoolExecutor"
136
})
137
public class ClassNameBasedRegistration {
138
}
139
```
140
141
### Selective Reflection Registration
142
143
```java
144
import io.quarkus.runtime.annotations.RegisterForReflection;
145
146
// Register only fields, not methods
147
@RegisterForReflection(
148
methods = false,
149
fields = true
150
)
151
public class FieldOnlyReflection {
152
private String data;
153
private int count;
154
155
// Methods will not be registered for reflection
156
public void someMethod() {
157
}
158
}
159
160
// Register only methods, not fields
161
@RegisterForReflection(
162
methods = true,
163
fields = false
164
)
165
public class MethodOnlyReflection {
166
// Fields will not be registered for reflection
167
private String data;
168
169
public void reflectiveMethod() {
170
// This method will be accessible via reflection
171
}
172
}
173
```
174
175
### Hierarchical Registration
176
177
```java
178
import io.quarkus.runtime.annotations.RegisterForReflection;
179
180
// Base class
181
public abstract class BaseEntity {
182
protected Long id;
183
protected String name;
184
185
public abstract void process();
186
}
187
188
// Register full hierarchy
189
@RegisterForReflection(registerFullHierarchy = true)
190
public class ConcreteEntity extends BaseEntity {
191
private String specificData;
192
193
@Override
194
public void process() {
195
// Implementation
196
}
197
}
198
```
199
200
### Serialization Support
201
202
```java
203
import io.quarkus.runtime.annotations.RegisterForReflection;
204
205
// Register for serialization (includes all necessary reflection metadata)
206
@RegisterForReflection(serialization = true)
207
public class SerializableData implements Serializable {
208
private String name;
209
private int value;
210
private List<String> items;
211
212
// Getters and setters
213
public String getName() { return name; }
214
public void setName(String name) { this.name = name; }
215
216
public int getValue() { return value; }
217
public void setValue(int value) { this.value = value; }
218
219
public List<String> getItems() { return items; }
220
public void setItems(List<String> items) { this.items = items; }
221
}
222
```
223
224
### Nested Class Handling
225
226
```java
227
import io.quarkus.runtime.annotations.RegisterForReflection;
228
229
// Include nested classes in registration
230
@RegisterForReflection(ignoreNested = false)
231
public class OuterClass {
232
private String outerField;
233
234
public static class StaticNestedClass {
235
private String nestedField;
236
}
237
238
public class InnerClass {
239
private String innerField;
240
}
241
}
242
243
// Exclude nested classes from registration
244
@RegisterForReflection(ignoreNested = true)
245
public class OuterClassExcludeNested {
246
private String outerField;
247
248
// These nested classes will NOT be registered
249
public static class NotRegistered {
250
private String field;
251
}
252
}
253
```
254
255
### Proxy Registration
256
257
```java
258
import io.quarkus.runtime.annotations.RegisterForProxy;
259
260
// Define interfaces
261
public interface UserService {
262
User findById(Long id);
263
List<User> findAll();
264
}
265
266
public interface PaymentService {
267
Payment processPayment(PaymentRequest request);
268
}
269
270
// Register interfaces for dynamic proxy creation
271
@RegisterForProxy({UserService.class, PaymentService.class})
272
public class ProxyConfiguration {
273
}
274
275
// Usage with dynamic proxies
276
public class ServiceProxyFactory {
277
278
public <T> T createProxy(Class<T> serviceInterface, InvocationHandler handler) {
279
return (T) Proxy.newProxyInstance(
280
serviceInterface.getClassLoader(),
281
new Class<?>[]{serviceInterface},
282
handler
283
);
284
}
285
286
public UserService createUserServiceProxy() {
287
return createProxy(UserService.class, (proxy, method, args) -> {
288
// Custom proxy logic
289
System.out.println("Invoking method: " + method.getName());
290
// Delegate to actual implementation or perform custom logic
291
return null;
292
});
293
}
294
}
295
```
296
297
### JSON Processing Registration
298
299
```java
300
import io.quarkus.runtime.annotations.RegisterForReflection;
301
import com.fasterxml.jackson.annotation.JsonProperty;
302
303
// Register DTOs for JSON serialization/deserialization
304
@RegisterForReflection
305
public class UserDto {
306
@JsonProperty("user_id")
307
private Long id;
308
309
@JsonProperty("user_name")
310
private String name;
311
312
@JsonProperty("email_address")
313
private String email;
314
315
// Constructors
316
public UserDto() {}
317
318
public UserDto(Long id, String name, String email) {
319
this.id = id;
320
this.name = name;
321
this.email = email;
322
}
323
324
// Getters and setters
325
public Long getId() { return id; }
326
public void setId(Long id) { this.id = id; }
327
328
public String getName() { return name; }
329
public void setName(String name) { this.name = name; }
330
331
public String getEmail() { return email; }
332
public void setEmail(String email) { this.email = email; }
333
}
334
335
// Register collection of related DTOs
336
@RegisterForReflection(targets = {
337
UserDto.class,
338
AddressDto.class,
339
ContactDto.class
340
})
341
public class DtoRegistration {
342
}
343
```
344
345
### JPA Entity Registration
346
347
```java
348
import io.quarkus.runtime.annotations.RegisterForReflection;
349
import jakarta.persistence.*;
350
351
// Register JPA entities for reflection
352
@RegisterForReflection(registerFullHierarchy = true)
353
@Entity
354
@Table(name = "users")
355
public class User {
356
@Id
357
@GeneratedValue(strategy = GenerationType.IDENTITY)
358
private Long id;
359
360
@Column(name = "username", unique = true, nullable = false)
361
private String username;
362
363
@Column(name = "email")
364
private String email;
365
366
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
367
private List<Order> orders = new ArrayList<>();
368
369
// Constructors, getters, setters
370
public User() {}
371
372
public User(String username, String email) {
373
this.username = username;
374
this.email = email;
375
}
376
377
// Getters and setters...
378
}
379
```
380
381
### Configuration-Based Registration
382
383
```java
384
import io.quarkus.runtime.annotations.RegisterForReflection;
385
386
// Register classes based on configuration
387
@RegisterForReflection(classNames = {
388
// Database drivers
389
"org.postgresql.Driver",
390
"org.h2.Driver",
391
392
// Third-party libraries
393
"org.apache.commons.lang3.StringUtils",
394
"org.apache.commons.collections4.CollectionUtils",
395
396
// Custom application classes
397
"com.mycompany.app.domain.User",
398
"com.mycompany.app.domain.Order"
399
})
400
public class LibraryReflectionConfig {
401
}
402
```
403
404
### Conditional Registration
405
406
```java
407
import io.quarkus.runtime.annotations.RegisterForReflection;
408
409
// Register different classes based on build profiles
410
public class ConditionalReflectionConfig {
411
412
// For development/test environments
413
@RegisterForReflection(targets = {
414
TestDataBuilder.class,
415
MockService.class
416
})
417
public static class DevelopmentReflectionConfig {
418
}
419
420
// For production environments
421
@RegisterForReflection(targets = {
422
ProductionService.class,
423
CacheManager.class
424
})
425
public static class ProductionReflectionConfig {
426
}
427
}
428
```
429
430
### Framework Integration
431
432
```java
433
import io.quarkus.runtime.annotations.RegisterForReflection;
434
import io.quarkus.runtime.annotations.RegisterForProxy;
435
436
// Register Spring Framework classes (if using Spring compatibility)
437
@RegisterForReflection(classNames = {
438
"org.springframework.beans.factory.annotation.Autowired",
439
"org.springframework.stereotype.Service",
440
"org.springframework.web.bind.annotation.RestController"
441
})
442
public class SpringCompatibilityRegistration {
443
}
444
445
// Register interfaces for CDI proxies
446
@RegisterForProxy({
447
jakarta.enterprise.context.ApplicationScoped.class,
448
jakarta.enterprise.context.RequestScoped.class
449
})
450
public class CdiProxyRegistration {
451
}
452
```
453
454
## Best Practices
455
456
### Registration Strategy
457
458
1. **Register specific classes** rather than entire packages when possible
459
2. **Use `targets`** parameter to register multiple related classes in one place
460
3. **Use `classNames`** for optional dependencies that might not be present
461
4. **Enable `serialization`** only when needed for performance
462
5. **Use `registerFullHierarchy`** carefully as it can register many classes
463
464
### Performance Considerations
465
466
1. **Minimize reflection registration** to reduce native image size
467
2. **Group related registrations** in dedicated configuration classes
468
3. **Use conditional registration** based on build profiles
469
4. **Test native images** thoroughly to ensure all required classes are registered
470
471
### Common Patterns
472
473
1. **DTO Registration**: Register all data transfer objects used in APIs
474
2. **Entity Registration**: Register JPA entities with full hierarchy
475
3. **Service Interface Registration**: Register interfaces used for dependency injection
476
4. **Third-party Library Registration**: Register external library classes that use reflection
477
5. **Framework Integration**: Register framework-specific classes for compatibility
478
479
### Debugging
480
481
When encountering reflection issues in native images:
482
483
1. **Enable reflection debugging** with `-H:+PrintAnalysis`
484
2. **Use `@RegisterForReflection`** to explicitly register missing classes
485
3. **Check build logs** for reflection warnings
486
4. **Test reflection access** in development mode first
487
5. **Use `registerFullHierarchy`** for complex class hierarchies