or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-lifecycle.mdbuild-time.mdconfiguration.mdindex.mdlogging.mdnative-image.mdruntime-context.md

native-image.mddocs/

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