0
# Build-time Configuration
1
2
Build-time APIs for customizing native image generation, including feature registration, reflection configuration, JNI access control, and lifecycle management. These APIs control what gets included in the final executable during the compilation phase.
3
4
## Capabilities
5
6
### Feature System
7
8
Comprehensive lifecycle hooks for customizing native image generation through well-defined phases.
9
10
```java { .api }
11
/**
12
* Interface for intercepting and customizing native image generation
13
*/
14
interface Feature {
15
/** Check if this feature should be included in the configuration */
16
default boolean isInConfiguration(IsInConfigurationAccess access) {
17
return true;
18
}
19
20
/** Called before analysis phase begins */
21
default void beforeAnalysis(BeforeAnalysisAccess access) {}
22
23
/** Called during analysis phase for iterative processing */
24
default void duringAnalysis(DuringAnalysisAccess access) {}
25
26
/** Called after analysis phase completes */
27
default void afterAnalysis(AfterAnalysisAccess access) {}
28
29
/** Called before compilation phase begins */
30
default void beforeCompilation(BeforeCompilationAccess access) {}
31
32
/** Called after heap layout is determined */
33
default void afterHeapLayout(AfterHeapLayoutAccess access) {}
34
35
/** Called before image writing */
36
default void beforeImageWrite(BeforeImageWriteAccess access) {}
37
38
/** Called after image generation completes */
39
default void afterImageWrite(AfterImageWriteAccess access) {}
40
41
/** Called when feature causes analysis iteration */
42
default void onAnalysisExit(OnAnalysisExitAccess access) {}
43
}
44
45
/**
46
* Access interface for configuration checking
47
*/
48
interface IsInConfigurationAccess {
49
/** Find optional class by name */
50
Class<?> findClassByName(String className);
51
52
/** Get application class loader */
53
ClassLoader getApplicationClassLoader();
54
}
55
56
/**
57
* Access interface for before analysis phase
58
*/
59
interface BeforeAnalysisAccess {
60
/** Register class as reachable */
61
void registerAsReachable(Class<?> clazz);
62
63
/** Register field as accessed */
64
void registerAsAccessed(Field field);
65
66
/** Register method as reachable */
67
void registerAsReachable(Method method);
68
69
/** Register constructor as reachable */
70
void registerAsReachable(Constructor<?> constructor);
71
72
/** Register for reflection */
73
void registerForReflectiveInstantiation(Class<?> clazz);
74
}
75
76
/**
77
* Access interface for during analysis phase
78
*/
79
interface DuringAnalysisAccess extends BeforeAnalysisAccess {
80
/** Check if analysis needs to be repeated */
81
boolean requireAnalysisIteration();
82
83
/** Get reachable classes */
84
Set<Class<?>> getReachableClasses();
85
86
/** Get reachable methods */
87
Set<Method> getReachableMethods();
88
}
89
```
90
91
**Usage Examples:**
92
93
```java
94
// Custom feature implementation
95
public class MyCustomFeature implements Feature {
96
@Override
97
public void beforeAnalysis(BeforeAnalysisAccess access) {
98
// Register classes for analysis
99
access.registerAsReachable(MyImportantClass.class);
100
access.registerForReflectiveInstantiation(MyReflectedClass.class);
101
}
102
103
@Override
104
public void duringAnalysis(DuringAnalysisAccess access) {
105
// Iterative processing during analysis
106
Set<Class<?>> reachable = access.getReachableClasses();
107
for (Class<?> clazz : reachable) {
108
if (needsSpecialHandling(clazz)) {
109
registerSpecialMethods(clazz, access);
110
access.requireAnalysisIteration();
111
}
112
}
113
}
114
115
@Override
116
public void afterAnalysis(AfterAnalysisAccess access) {
117
// Final processing after analysis
118
System.out.println("Analysis complete, proceeding to compilation");
119
}
120
}
121
122
// Register the feature
123
// (typically done via META-INF/services/org.graalvm.nativeimage.hosted.Feature)
124
```
125
126
### Runtime Reflection Configuration
127
128
Register classes, methods, and fields for runtime reflection access.
129
130
```java { .api }
131
/**
132
* Configuration API for runtime reflection access
133
*/
134
class RuntimeReflection {
135
/** Register classes for runtime reflection */
136
static void register(Class<?>... classes);
137
138
/** Register constructors for runtime reflection */
139
static void register(Constructor<?>... constructors);
140
141
/** Register methods for runtime reflection */
142
static void register(Method... methods);
143
144
/** Register fields for runtime reflection */
145
static void register(Field... fields);
146
147
/** Register all declared constructors of classes */
148
static void registerAllDeclaredConstructors(Class<?>... classes);
149
150
/** Register all declared methods of classes */
151
static void registerAllDeclaredMethods(Class<?>... classes);
152
153
/** Register all declared fields of classes */
154
static void registerAllDeclaredFields(Class<?>... classes);
155
156
/** Register classes for reflective instantiation */
157
static void registerForReflectiveInstantiation(Class<?>... classes);
158
}
159
```
160
161
**Usage Examples:**
162
163
```java
164
// Register specific elements
165
RuntimeReflection.register(MyClass.class);
166
RuntimeReflection.register(MyClass.class.getDeclaredMethod("myMethod"));
167
RuntimeReflection.register(MyClass.class.getDeclaredField("myField"));
168
169
// Register all elements of a class
170
RuntimeReflection.registerAllDeclaredMethods(MyClass.class);
171
RuntimeReflection.registerAllDeclaredFields(MyClass.class);
172
173
// Register for instantiation
174
RuntimeReflection.registerForReflectiveInstantiation(MyClass.class);
175
176
// In a Feature
177
public class ReflectionFeature implements Feature {
178
@Override
179
public void beforeAnalysis(BeforeAnalysisAccess access) {
180
// Bulk registration
181
RuntimeReflection.register(
182
String.class,
183
List.class,
184
Map.class
185
);
186
187
// Dynamic registration based on classpath scanning
188
registerJsonClasses();
189
}
190
191
private void registerJsonClasses() {
192
// Find and register classes with JSON annotations
193
for (Class<?> clazz : findClassesWithAnnotation(JsonSerializable.class)) {
194
RuntimeReflection.registerAllDeclaredFields(clazz);
195
RuntimeReflection.registerAllDeclaredConstructors(clazz);
196
}
197
}
198
}
199
```
200
201
### JNI Access Configuration
202
203
Configure JNI access for runtime native method calls.
204
205
```java { .api }
206
/**
207
* Configuration API for runtime JNI access
208
*/
209
class RuntimeJNIAccess {
210
/** Register classes for JNI access */
211
static void register(Class<?>... classes);
212
213
/** Register constructors for JNI access */
214
static void register(Constructor<?>... constructors);
215
216
/** Register methods for JNI access */
217
static void register(Method... methods);
218
219
/** Register fields for JNI access */
220
static void register(Field... fields);
221
222
/** Register all declared constructors for JNI */
223
static void registerAllDeclaredConstructors(Class<?>... classes);
224
225
/** Register all declared methods for JNI */
226
static void registerAllDeclaredMethods(Class<?>... classes);
227
228
/** Register all declared fields for JNI */
229
static void registerAllDeclaredFields(Class<?>... classes);
230
}
231
```
232
233
**Usage Examples:**
234
235
```java
236
// Register JNI-accessible elements
237
RuntimeJNIAccess.register(NativeInterface.class);
238
RuntimeJNIAccess.register(
239
NativeInterface.class.getDeclaredMethod("nativeCallback", int.class)
240
);
241
242
// Register all JNI methods
243
RuntimeJNIAccess.registerAllDeclaredMethods(JNIHelper.class);
244
245
// In a Feature for JNI libraries
246
public class JNIFeature implements Feature {
247
@Override
248
public void beforeAnalysis(BeforeAnalysisAccess access) {
249
// Register classes used by native libraries
250
RuntimeJNIAccess.register(
251
CallbackHandler.class,
252
DataProcessor.class,
253
ErrorReporter.class
254
);
255
256
// Register specific methods called from native code
257
try {
258
Method callback = CallbackHandler.class.getDeclaredMethod("onEvent", String.class);
259
RuntimeJNIAccess.register(callback);
260
} catch (NoSuchMethodException e) {
261
throw new RuntimeException(e);
262
}
263
}
264
}
265
```
266
267
### Class Initialization Configuration
268
269
Control when classes are initialized during build time vs runtime.
270
271
```java { .api }
272
/**
273
* Configuration API for controlling class initialization timing
274
*/
275
class RuntimeClassInitialization {
276
/** Initialize classes at build time */
277
static void initializeAtBuildTime(Class<?>... classes);
278
279
/** Initialize classes at build time by name */
280
static void initializeAtBuildTime(String... classNames);
281
282
/** Initialize classes at runtime */
283
static void initializeAtRunTime(Class<?>... classes);
284
285
/** Initialize classes at runtime by name */
286
static void initializeAtRunTime(String... classNames);
287
288
/** Initialize packages at build time */
289
static void initializeAtBuildTimePackage(String... packageNames);
290
291
/** Initialize packages at runtime */
292
static void initializeAtRunTimePackage(String... packageNames);
293
}
294
```
295
296
**Usage Examples:**
297
298
```java
299
// Build-time initialization for constants and utilities
300
RuntimeClassInitialization.initializeAtBuildTime(
301
Constants.class,
302
UtilityClass.class,
303
"com.example.config"
304
);
305
306
// Runtime initialization for stateful classes
307
RuntimeClassInitialization.initializeAtRunTime(
308
DatabaseConnection.class,
309
ThreadPool.class,
310
"com.example.runtime"
311
);
312
313
// Package-level control
314
RuntimeClassInitialization.initializeAtBuildTimePackage("com.example.constants");
315
RuntimeClassInitialization.initializeAtRunTimePackage("com.example.services");
316
317
// In a Feature
318
public class InitializationFeature implements Feature {
319
@Override
320
public void beforeAnalysis(BeforeAnalysisAccess access) {
321
// Configure based on application needs
322
configureLogging();
323
configureDatabase();
324
}
325
326
private void configureLogging() {
327
// Logging can be initialized at build time
328
RuntimeClassInitialization.initializeAtBuildTime(
329
"org.slf4j",
330
"ch.qos.logback.classic",
331
"ch.qos.logback.core"
332
);
333
}
334
335
private void configureDatabase() {
336
// Database connections must be runtime
337
RuntimeClassInitialization.initializeAtRunTime(
338
"javax.sql",
339
"com.zaxxer.hikari"
340
);
341
}
342
}
343
```
344
345
### Additional Configuration APIs
346
347
Other build-time configuration capabilities.
348
349
```java { .api }
350
/**
351
* Configuration API for dynamic proxy creation
352
*/
353
class RuntimeProxyCreation {
354
/** Register interfaces for dynamic proxy creation */
355
static void register(Class<?>... interfaces);
356
}
357
358
/**
359
* Configuration API for serialization support
360
*/
361
class RuntimeSerialization {
362
/** Register classes for serialization */
363
static void register(Class<?>... classes);
364
365
/** Register classes for serialization by name */
366
static void register(String... classNames);
367
}
368
369
/**
370
* Configuration API for resource access
371
*/
372
class RuntimeResourceAccess {
373
/** Register resources for runtime access */
374
static void addResource(String resource);
375
376
/** Register resource bundles */
377
static void addResourceBundle(String bundleName);
378
379
/** Register resource patterns */
380
static void addResourcePattern(String pattern);
381
}
382
383
/**
384
* Configuration API for system properties
385
*/
386
class RuntimeSystemProperties {
387
/** Set system property for runtime */
388
static void set(String key, String value);
389
390
/** Register system property for access */
391
static void register(String key);
392
}
393
394
/**
395
* Configuration API for foreign function access
396
*/
397
class RuntimeForeignAccess {
398
/** Register foreign functions for runtime access */
399
static void register(String... functions);
400
}
401
402
/**
403
* Transform field values during image building
404
*/
405
interface FieldValueTransformer {
406
/** Transform field value during build */
407
Object transform(Field field, Object receiver, Object value);
408
}
409
```
410
411
**Usage Examples:**
412
413
```java
414
// Proxy configuration
415
RuntimeProxyCreation.register(MyInterface.class, AnotherInterface.class);
416
417
// Serialization support
418
RuntimeSerialization.register(
419
MySerializableClass.class,
420
"com.example.data.UserData",
421
"com.example.data.Configuration"
422
);
423
424
// Resource access
425
RuntimeResourceAccess.addResource("config.properties");
426
RuntimeResourceAccess.addResourceBundle("messages");
427
RuntimeResourceAccess.addResourcePattern("static/.*\\.html");
428
429
// System properties
430
RuntimeSystemProperties.set("app.version", "1.0.0");
431
RuntimeSystemProperties.register("user.home");
432
433
// Foreign function access
434
RuntimeForeignAccess.register("malloc", "free", "strlen");
435
436
// Field transformation
437
public class ConfigTransformer implements FieldValueTransformer {
438
@Override
439
public Object transform(Field field, Object receiver, Object value) {
440
if (field.getName().equals("databaseUrl")) {
441
// Transform database URL at build time
442
return processConfigValue((String) value);
443
}
444
return value;
445
}
446
}
447
```
448
449
### Complete Feature Example
450
451
```java
452
/**
453
* Comprehensive feature demonstrating multiple configuration aspects
454
*/
455
public class ApplicationFeature implements Feature {
456
@Override
457
public void beforeAnalysis(BeforeAnalysisAccess access) {
458
configureReflection();
459
configureJNI();
460
configureInitialization();
461
configureResources();
462
configureSerialization();
463
}
464
465
private void configureReflection() {
466
// Register framework classes
467
RuntimeReflection.register(
468
MyController.class,
469
MyService.class,
470
MyRepository.class
471
);
472
473
// Register annotation-driven components
474
for (Class<?> clazz : findAnnotatedClasses(Component.class)) {
475
RuntimeReflection.registerAllDeclaredMethods(clazz);
476
RuntimeReflection.registerForReflectiveInstantiation(clazz);
477
}
478
}
479
480
private void configureJNI() {
481
// Register native method classes
482
RuntimeJNIAccess.register(NativeLibrary.class);
483
RuntimeJNIAccess.registerAllDeclaredMethods(JNICallback.class);
484
}
485
486
private void configureInitialization() {
487
// Build-time initialization for constants
488
RuntimeClassInitialization.initializeAtBuildTime(
489
"com.example.constants",
490
"com.example.config"
491
);
492
493
// Runtime initialization for stateful components
494
RuntimeClassInitialization.initializeAtRunTime(
495
"com.example.database",
496
"com.example.network"
497
);
498
}
499
500
private void configureResources() {
501
// Application resources
502
RuntimeResourceAccess.addResource("application.properties");
503
RuntimeResourceAccess.addResourcePattern("templates/.*");
504
RuntimeResourceAccess.addResourceBundle("messages");
505
}
506
507
private void configureSerialization() {
508
// DTO classes for JSON serialization
509
for (Class<?> dto : findDTOClasses()) {
510
RuntimeSerialization.register(dto);
511
RuntimeReflection.registerAllDeclaredFields(dto);
512
}
513
}
514
515
@Override
516
public void duringAnalysis(DuringAnalysisAccess access) {
517
// Dynamic registration based on analysis results
518
boolean hasNewReachableClasses = false;
519
520
for (Class<?> clazz : access.getReachableClasses()) {
521
if (isFrameworkClass(clazz)) {
522
registerFrameworkRequirements(clazz, access);
523
hasNewReachableClasses = true;
524
}
525
}
526
527
if (hasNewReachableClasses) {
528
access.requireAnalysisIteration();
529
}
530
}
531
532
@Override
533
public void afterAnalysis(AfterAnalysisAccess access) {
534
// Validation and final setup
535
validateConfiguration();
536
generateBuildReport();
537
}
538
}
539
```
540
541
This build-time configuration system provides comprehensive control over native image generation, enabling applications to precisely specify what functionality should be available at runtime while optimizing the final executable size and performance.