or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-processing.mdaot-optimization.mdcore-infrastructure.mdenvironment-config.mdindex.mdresource-management.mdtask-execution.mdtype-conversion.mdutilities.md

aot-optimization.mddocs/

0

# AOT Optimization and Native Images

1

2

Spring Core provides comprehensive Ahead-of-Time (AOT) compilation support that enables applications to be compiled to native images using GraalVM. This includes runtime hints registration, reflection optimization, and resource bundling for optimal native image performance.

3

4

## AOT Detection and Configuration

5

6

Spring provides utilities to detect when AOT optimizations are available and should be used.

7

8

**AotDetector Utility**

9

```java { .api }

10

public final class AotDetector {

11

public static final String AOT_ENABLED = "spring.aot.enabled";

12

13

public static boolean useGeneratedArtifacts();

14

15

// Private constructor - utility class

16

}

17

```

18

19

**Usage Examples**

20

```java

21

// Check if AOT optimizations should be used

22

boolean shouldUseAot = AotDetector.useGeneratedArtifacts();

23

if (shouldUseAot) {

24

// Use pre-compiled AOT optimizations

25

loadPreCompiledBeans();

26

} else {

27

// Use standard runtime reflection-based initialization

28

loadStandardBeans();

29

}

30

31

// Enable AOT via system property

32

System.setProperty("spring.aot.enabled", "true");

33

34

// Or via environment variable

35

// SPRING_AOT_ENABLED=true

36

37

// Conditional logic based on AOT availability

38

@Component

39

public class ConditionalService {

40

41

public ConditionalService() {

42

if (AotDetector.useGeneratedArtifacts()) {

43

initializeForNativeImage();

44

} else {

45

initializeForJvm();

46

}

47

}

48

}

49

```

50

51

## Runtime Hints System

52

53

The runtime hints system allows applications to register metadata that helps AOT compilation tools understand which classes, methods, fields, and resources need to be available at runtime.

54

55

**RuntimeHints Class**

56

```java { .api }

57

public final class RuntimeHints {

58

public ReflectionHints reflection();

59

public ResourceHints resources();

60

public SerializationHints serialization();

61

public ProxyHints proxies();

62

public JniHints jni();

63

}

64

```

65

66

**RuntimeHintsRegistrar Interface**

67

```java { .api }

68

@FunctionalInterface

69

public interface RuntimeHintsRegistrar {

70

void registerHints(RuntimeHints hints, ClassLoader classLoader);

71

}

72

```

73

74

**Usage Examples**

75

```java

76

// Implement custom runtime hints registrar

77

public class MyApplicationRuntimeHints implements RuntimeHintsRegistrar {

78

79

@Override

80

public void registerHints(RuntimeHints hints, ClassLoader classLoader) {

81

// Register reflection hints

82

hints.reflection()

83

.registerType(MyService.class, MemberCategory.INVOKE_PUBLIC_METHODS)

84

.registerType(MyEntity.class, MemberCategory.DECLARED_FIELDS)

85

.registerConstructor(MyController.class.getConstructor(MyService.class), ExecutableMode.INVOKE);

86

87

// Register resource hints

88

hints.resources()

89

.registerPattern("templates/*.html")

90

.registerPattern("static/css/*.css")

91

.registerResourceBundle("messages");

92

93

// Register serialization hints

94

hints.serialization()

95

.registerType(MyDto.class)

96

.registerType(MyResponse.class);

97

98

// Register proxy hints

99

hints.proxies()

100

.registerJdkProxy(MyInterface.class, AnotherInterface.class);

101

}

102

}

103

104

// Register hints programmatically

105

RuntimeHints hints = new RuntimeHints();

106

MyApplicationRuntimeHints registrar = new MyApplicationRuntimeHints();

107

registrar.registerHints(hints, getClass().getClassLoader());

108

```

109

110

## Reflection Hints

111

112

The reflection hints system provides fine-grained control over which classes, methods, fields, and constructors should be available for reflection in native images.

113

114

**ReflectionHints Class**

115

```java { .api }

116

public final class ReflectionHints {

117

// Type registration

118

public Builder registerType(Class<?> type, MemberCategory... memberCategories);

119

public Builder registerType(TypeReference type, MemberCategory... memberCategories);

120

public Builder registerTypeIfPresent(ClassLoader classLoader, String typeName, MemberCategory... memberCategories);

121

122

// Constructor registration

123

public Builder registerConstructor(Constructor<?> constructor, ExecutableMode executableMode);

124

public Builder registerConstructor(TypeReference type, List<TypeReference> parameterTypes, ExecutableMode executableMode);

125

126

// Method registration

127

public Builder registerMethod(Method method, ExecutableMode executableMode);

128

public Builder registerMethod(TypeReference type, String methodName, List<TypeReference> parameterTypes, ExecutableMode executableMode);

129

130

// Field registration

131

public Builder registerField(Field field);

132

public Builder registerField(TypeReference type, String fieldName);

133

134

// Query methods

135

public Stream<TypeHint> typeHints();

136

public TypeHint getTypeHint(Class<?> type);

137

public TypeHint getTypeHint(TypeReference type);

138

}

139

140

public enum MemberCategory {

141

INTROSPECT_PUBLIC_CONSTRUCTORS,

142

INTROSPECT_DECLARED_CONSTRUCTORS,

143

INVOKE_PUBLIC_CONSTRUCTORS,

144

INVOKE_DECLARED_CONSTRUCTORS,

145

INTROSPECT_PUBLIC_METHODS,

146

INTROSPECT_DECLARED_METHODS,

147

INVOKE_PUBLIC_METHODS,

148

INVOKE_DECLARED_METHODS,

149

INTROSPECT_PUBLIC_FIELDS,

150

INTROSPECT_DECLARED_FIELDS,

151

PUBLIC_FIELDS,

152

DECLARED_FIELDS

153

}

154

155

public enum ExecutableMode {

156

INTROSPECT,

157

INVOKE

158

}

159

```

160

161

**Usage Examples**

162

```java

163

// Register comprehensive reflection hints

164

RuntimeHints hints = new RuntimeHints();

165

ReflectionHints reflection = hints.reflection();

166

167

// Register entity classes for full reflection access

168

reflection.registerType(User.class,

169

MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,

170

MemberCategory.DECLARED_FIELDS,

171

MemberCategory.INVOKE_PUBLIC_METHODS);

172

173

// Register service classes for method invocation

174

reflection.registerType(UserService.class, MemberCategory.INVOKE_PUBLIC_METHODS);

175

176

// Register specific constructors

177

Constructor<UserController> constructor = UserController.class.getConstructor(UserService.class);

178

reflection.registerConstructor(constructor, ExecutableMode.INVOKE);

179

180

// Register specific methods

181

Method findByIdMethod = UserService.class.getMethod("findById", Long.class);

182

reflection.registerMethod(findByIdMethod, ExecutableMode.INVOKE);

183

184

// Register fields for serialization frameworks

185

Field userIdField = User.class.getDeclaredField("id");

186

reflection.registerField(userIdField);

187

188

// Conditional registration based on classpath presence

189

reflection.registerTypeIfPresent(classLoader,

190

"com.fasterxml.jackson.databind.ObjectMapper",

191

MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,

192

MemberCategory.INVOKE_PUBLIC_METHODS);

193

194

// Register generic types

195

reflection.registerType(TypeReference.of("com.example.GenericService<java.lang.String>"),

196

MemberCategory.INVOKE_PUBLIC_METHODS);

197

198

// Check registered hints

199

TypeHint userHint = reflection.getTypeHint(User.class);

200

if (userHint != null) {

201

boolean hasConstructorHints = !userHint.constructorHints().isEmpty();

202

boolean hasMethodHints = !userHint.methodHints().isEmpty();

203

}

204

```

205

206

## Resource Hints

207

208

Resource hints specify which resources should be bundled into the native image and available at runtime.

209

210

**ResourceHints Class**

211

```java { .api }

212

public final class ResourceHints {

213

// Pattern-based registration

214

public Builder registerPattern(String pattern);

215

public Builder registerPattern(ResourcePatternHint hint);

216

217

// Type-based registration

218

public Builder registerType(Class<?> type);

219

public Builder registerTypeIfPresent(ClassLoader classLoader, String typeName);

220

221

// Resource bundle registration

222

public Builder registerResourceBundle(String baseName);

223

224

// Query methods

225

public Stream<ResourcePatternHint> resourcePatternHints();

226

public Stream<ResourceBundleHint> resourceBundleHints();

227

}

228

229

public final class ResourcePatternHint {

230

public static ResourcePatternHint of(String pattern);

231

public static ResourcePatternHint of(String pattern, Predicate<String> filter);

232

233

public String getPattern();

234

public Predicate<String> getFilter();

235

}

236

```

237

238

**Usage Examples**

239

```java

240

// Register resource patterns

241

RuntimeHints hints = new RuntimeHints();

242

ResourceHints resources = hints.resources();

243

244

// Static web resources

245

resources.registerPattern("static/**")

246

.registerPattern("templates/*.html")

247

.registerPattern("css/*.css")

248

.registerPattern("js/*.js");

249

250

// Configuration files

251

resources.registerPattern("application*.properties")

252

.registerPattern("application*.yml")

253

.registerPattern("config/*.xml");

254

255

// Resource bundles for internationalization

256

resources.registerResourceBundle("messages")

257

.registerResourceBundle("validation")

258

.registerResourceBundle("labels");

259

260

// Class-based resource registration (includes class and related resources)

261

resources.registerType(MyController.class); // Includes MyController.class and package resources

262

resources.registerType(MyService.class);

263

264

// Conditional resource registration

265

resources.registerTypeIfPresent(classLoader, "com.example.OptionalService");

266

267

// Advanced pattern with filtering

268

ResourcePatternHint filteredHint = ResourcePatternHint.of("data/*.json",

269

filename -> !filename.contains("test"));

270

resources.registerPattern(filteredHint);

271

272

// Register resources for specific packages

273

resources.registerPattern("com/example/templates/**")

274

.registerPattern("META-INF/spring/**")

275

.registerPattern("META-INF/services/**");

276

```

277

278

## Serialization Hints

279

280

Serialization hints specify which classes need to be available for serialization/deserialization in native images.

281

282

**SerializationHints Class**

283

```java { .api }

284

public final class SerializationHints {

285

// Type registration

286

public Builder registerType(Class<?> type);

287

public Builder registerType(TypeReference type);

288

public Builder registerTypeIfPresent(ClassLoader classLoader, String typeName);

289

290

// Query methods

291

public Stream<JavaSerializationHint> javaSerializationHints();

292

}

293

```

294

295

**Usage Examples**

296

```java

297

// Register serialization hints

298

RuntimeHints hints = new RuntimeHints();

299

SerializationHints serialization = hints.serialization();

300

301

// Register DTOs and entities for JSON serialization

302

serialization.registerType(UserDto.class)

303

.registerType(OrderDto.class)

304

.registerType(ProductDto.class);

305

306

// Register domain entities

307

serialization.registerType(User.class)

308

.registerType(Order.class)

309

.registerType(Product.class);

310

311

// Register generic types

312

serialization.registerType(TypeReference.of("java.util.List<com.example.UserDto>"))

313

.registerType(TypeReference.of("java.util.Map<java.lang.String, java.lang.Object>"));

314

315

// Conditional registration for optional dependencies

316

serialization.registerTypeIfPresent(classLoader, "com.example.CacheEntry");

317

318

// Register collections and common types

319

serialization.registerType(ArrayList.class)

320

.registerType(HashMap.class)

321

.registerType(LinkedHashMap.class);

322

```

323

324

## Proxy Hints

325

326

Proxy hints specify which interfaces should be available for JDK dynamic proxy creation.

327

328

**ProxyHints Class**

329

```java { .api }

330

public final class ProxyHints {

331

// JDK proxy registration

332

public Builder registerJdkProxy(Class<?>... interfaces);

333

public Builder registerJdkProxy(TypeReference... interfaces);

334

public Builder registerJdkProxy(JdkProxyHint hint);

335

336

// Query methods

337

public Stream<JdkProxyHint> jdkProxyHints();

338

}

339

```

340

341

**Usage Examples**

342

```java

343

// Register proxy hints

344

RuntimeHints hints = new RuntimeHints();

345

ProxyHints proxies = hints.proxies();

346

347

// Register service interfaces for proxy creation

348

proxies.registerJdkProxy(UserService.class)

349

.registerJdkProxy(OrderService.class)

350

.registerJdkProxy(ProductService.class);

351

352

// Register multiple interfaces for single proxy

353

proxies.registerJdkProxy(MyService.class, Serializable.class, Cloneable.class);

354

355

// Register transaction proxies

356

proxies.registerJdkProxy(

357

TypeReference.of("org.springframework.transaction.interceptor.TransactionalProxy"),

358

TypeReference.of("org.springframework.aop.SpringProxy"));

359

360

// Register common Spring proxy interfaces

361

proxies.registerJdkProxy(

362

TypeReference.of("org.springframework.aop.framework.Advised"),

363

TypeReference.of("org.springframework.core.DecoratingProxy"));

364

```

365

366

## Type References

367

368

Type references provide a way to specify types that may not be available on the classpath at compile time.

369

370

**TypeReference Interface**

371

```java { .api }

372

public interface TypeReference {

373

String getName();

374

String getCanonicalName();

375

String getPackageName();

376

String getSimpleName();

377

TypeReference getEnclosingType();

378

379

// Static factory methods

380

static TypeReference of(String name);

381

static TypeReference of(Class<?> type);

382

}

383

```

384

385

**Usage Examples**

386

```java

387

// Create type references for optional dependencies

388

TypeReference optionalType = TypeReference.of("com.example.OptionalService");

389

TypeReference genericType = TypeReference.of("java.util.List<java.lang.String>");

390

TypeReference arrayType = TypeReference.of("[Lcom.example.User;");

391

392

// Use in hints registration

393

RuntimeHints hints = new RuntimeHints();

394

395

hints.reflection()

396

.registerType(optionalType, MemberCategory.INVOKE_PUBLIC_METHODS)

397

.registerType(genericType, MemberCategory.INTROSPECT_PUBLIC_METHODS);

398

399

hints.serialization()

400

.registerType(optionalType);

401

402

// Type reference utilities

403

String packageName = optionalType.getPackageName(); // "com.example"

404

String simpleName = optionalType.getSimpleName(); // "OptionalService"

405

String canonicalName = optionalType.getCanonicalName(); // "com.example.OptionalService"

406

```

407

408

## Native Image Detection

409

410

**NativeDetector Utility**

411

```java { .api }

412

public final class NativeDetector {

413

public static boolean inNativeImage();

414

415

// Private constructor - utility class

416

}

417

```

418

419

**Usage Examples**

420

```java

421

// Runtime behavior adaptation for native images

422

public class AdaptiveService {

423

424

public void initialize() {

425

if (NativeDetector.inNativeImage()) {

426

// Native image optimized initialization

427

initializeForNativeImage();

428

} else {

429

// JVM initialization with full reflection

430

initializeForJvm();

431

}

432

}

433

434

private void initializeForNativeImage() {

435

// Use pre-registered beans and avoid reflection

436

usePrecompiledConfiguration();

437

}

438

439

private void initializeForJvm() {

440

// Use standard Spring reflection-based initialization

441

useReflectionBasedConfiguration();

442

}

443

}

444

445

// Conditional bean creation

446

@Configuration

447

public class ConditionalConfiguration {

448

449

@Bean

450

@ConditionalOnExpression("!T(org.springframework.core.NativeDetector).inNativeImage()")

451

public ReflectionBasedService reflectionService() {

452

return new ReflectionBasedService();

453

}

454

455

@Bean

456

@ConditionalOnExpression("T(org.springframework.core.NativeDetector).inNativeImage()")

457

public PrecompiledService precompiledService() {

458

return new PrecompiledService();

459

}

460

}

461

```

462

463

## Best Practices for AOT Optimization

464

465

**Comprehensive Hints Registration**

466

```java

467

@Component

468

public class ComprehensiveHintsRegistrar implements RuntimeHintsRegistrar {

469

470

@Override

471

public void registerHints(RuntimeHints hints, ClassLoader classLoader) {

472

registerReflectionHints(hints);

473

registerResourceHints(hints);

474

registerSerializationHints(hints);

475

registerProxyHints(hints);

476

}

477

478

private void registerReflectionHints(RuntimeHints hints) {

479

// Entity classes need field access for JPA/serialization

480

hints.reflection()

481

.registerType(User.class,

482

MemberCategory.DECLARED_FIELDS,

483

MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS)

484

.registerType(Order.class,

485

MemberCategory.DECLARED_FIELDS,

486

MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS);

487

488

// Service classes need method invocation

489

hints.reflection()

490

.registerType(UserService.class, MemberCategory.INVOKE_PUBLIC_METHODS)

491

.registerType(OrderService.class, MemberCategory.INVOKE_PUBLIC_METHODS);

492

493

// Controllers need full reflection access

494

hints.reflection()

495

.registerType(UserController.class,

496

MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS,

497

MemberCategory.INVOKE_PUBLIC_METHODS,

498

MemberCategory.DECLARED_FIELDS);

499

}

500

501

private void registerResourceHints(RuntimeHints hints) {

502

// Application configuration

503

hints.resources()

504

.registerPattern("application*.properties")

505

.registerPattern("application*.yml")

506

.registerPattern("bootstrap*.properties");

507

508

// Web resources

509

hints.resources()

510

.registerPattern("static/**")

511

.registerPattern("templates/**")

512

.registerPattern("public/**");

513

514

// Message bundles

515

hints.resources()

516

.registerResourceBundle("messages")

517

.registerResourceBundle("ValidationMessages");

518

}

519

520

private void registerSerializationHints(RuntimeHints hints) {

521

// DTOs for JSON serialization

522

hints.serialization()

523

.registerType(UserDto.class)

524

.registerType(OrderDto.class)

525

.registerType(ApiResponse.class);

526

527

// Collection types commonly used in serialization

528

hints.serialization()

529

.registerType(ArrayList.class)

530

.registerType(HashMap.class)

531

.registerType(LinkedHashMap.class);

532

}

533

534

private void registerProxyHints(RuntimeHints hints) {

535

// Service interfaces for AOP proxying

536

hints.proxies()

537

.registerJdkProxy(UserService.class)

538

.registerJdkProxy(OrderService.class);

539

540

// Transaction and caching proxies

541

hints.proxies()

542

.registerJdkProxy(

543

TypeReference.of("org.springframework.transaction.interceptor.TransactionalProxy"),

544

TypeReference.of("org.springframework.aop.SpringProxy"));

545

}

546

}

547

```

548

549

This comprehensive AOT optimization system enables Spring applications to be compiled to efficient native images while maintaining the framework's powerful features and developer experience.