0
# Class File Builder
1
2
Fluent builder patterns for constructing Java class files programmatically with full type safety and validation. This package enables the creation of class files from scratch using a chainable API that ensures structural correctness and proper constant pool management.
3
4
## Capabilities
5
6
### ClassFile Builder
7
8
Create Java class files programmatically using a fluent builder pattern with validation and automatic constant pool management.
9
10
```java { .api }
11
/**
12
* Fluent builder for creating ClassFile instances with validation
13
*/
14
public class ClassFileBuilder {
15
/**
16
* Set the minor version number for the class file
17
* @param version Minor version (typically 0)
18
* @return This builder instance for chaining
19
*/
20
public ClassFileBuilder minor_version(int version);
21
22
/**
23
* Set the major version number for the class file
24
* @param version Major version (45 for Java 1.1, 52 for Java 8, etc.)
25
* @return This builder instance for chaining
26
*/
27
public ClassFileBuilder major_version(int version);
28
29
/**
30
* Set the access flags for the class
31
* @param flags Access flags (ACC_PUBLIC, ACC_FINAL, etc.)
32
* @return This builder instance for chaining
33
*/
34
public ClassFileBuilder access(int flags);
35
36
/**
37
* Set the name of this class
38
* @param className Fully qualified class name (e.g., "java/lang/String")
39
* @return This builder instance for chaining
40
*/
41
public ClassFileBuilder this_class(String className);
42
43
/**
44
* Set the superclass name
45
* @param superClassName Fully qualified superclass name (null for java.lang.Object)
46
* @return This builder instance for chaining
47
*/
48
public ClassFileBuilder super_class(String superClassName);
49
50
/**
51
* Add implemented interfaces
52
* @param interfaceNames Array of interface names
53
* @return This builder instance for chaining
54
*/
55
public ClassFileBuilder interfaces(String... interfaceNames);
56
57
/**
58
* Add field information to the class
59
* @param fields Array of FieldInfo instances
60
* @return This builder instance for chaining
61
*/
62
public ClassFileBuilder fields(FieldInfo... fields);
63
64
/**
65
* Add method information to the class
66
* @param methods Array of MethodInfo instances
67
* @return This builder instance for chaining
68
*/
69
public ClassFileBuilder methods(MethodInfo... methods);
70
71
/**
72
* Add class-level attributes
73
* @param attributes Array of Attribute instances
74
* @return This builder instance for chaining
75
*/
76
public ClassFileBuilder attributes(Attribute... attributes);
77
78
/**
79
* Build the final ClassFile instance with validation
80
* @return Complete ClassFile ready for serialization
81
* @throws IllegalStateException if required fields are missing
82
*/
83
public ClassFile build();
84
}
85
```
86
87
**Usage Example:**
88
89
```java
90
import aQute.bnd.classfile.ClassFile;
91
import aQute.bnd.classfile.builder.ClassFileBuilder;
92
import static aQute.bnd.classfile.ClassFile.*;
93
94
// Create a simple class file
95
ClassFile classFile = new ClassFileBuilder()
96
.major_version(52) // Java 8
97
.minor_version(0)
98
.access(ACC_PUBLIC | ACC_SUPER)
99
.this_class("com/example/MyClass")
100
.super_class("java/lang/Object")
101
.interfaces("java/lang/Runnable")
102
.build();
103
104
// Write to file
105
try (DataOutputStream out = new DataOutputStream(Files.newOutputStream(outputPath))) {
106
classFile.write(out);
107
}
108
```
109
110
### Mutable Constant Pool
111
112
Build constant pools incrementally with automatic duplicate detection and reference management.
113
114
```java { .api }
115
/**
116
* Mutable version of ConstantPool for building class files
117
*/
118
public class MutableConstantPool extends ConstantPool {
119
/**
120
* Create an empty mutable constant pool
121
*/
122
public MutableConstantPool();
123
124
/**
125
* Create a mutable constant pool from an existing one
126
* @param constantPool Existing constant pool to copy
127
*/
128
public MutableConstantPool(ConstantPool constantPool);
129
130
/**
131
* Get the current size of the constant pool
132
* @return Number of entries in the pool
133
*/
134
public int size();
135
136
/**
137
* Get an entry from the constant pool
138
* @param index Entry index (1-based)
139
* @return Constant pool entry
140
*/
141
public Object entry(int index);
142
143
/**
144
* Set an entry in the constant pool
145
* @param index Entry index (1-based)
146
* @param entry Constant pool entry
147
* @return The entry that was set
148
*/
149
public Object entry(int index, Object entry);
150
151
/**
152
* Add an entry to the constant pool with automatic duplicate detection
153
* @param type Expected entry type for validation
154
* @param supplier Supplier that creates the entry if not already present
155
* @return The entry (existing or newly created)
156
*/
157
public <T> T add(Class<T> type, Supplier<T> supplier);
158
}
159
```
160
161
**Usage Example:**
162
163
```java
164
import aQute.bnd.classfile.builder.MutableConstantPool;
165
166
// Create and populate a constant pool
167
MutableConstantPool pool = new MutableConstantPool();
168
169
// Add UTF-8 strings (automatically deduplicates)
170
String className = pool.add(String.class, () -> "com/example/MyClass");
171
String superClass = pool.add(String.class, () -> "java/lang/Object");
172
173
// Add class references
174
ClassInfo thisClass = pool.add(ClassInfo.class, () -> new ClassInfo(className));
175
ClassInfo superClassInfo = pool.add(ClassInfo.class, () -> new ClassInfo(superClass));
176
177
System.out.println("Pool size: " + pool.size());
178
```
179
180
### Field Builder
181
182
Create field information with proper constant pool integration.
183
184
```java { .api }
185
/**
186
* Builder for creating FieldInfo instances
187
*/
188
public class FieldInfoBuilder {
189
/**
190
* Set field access flags
191
* @param flags Access flags (ACC_PUBLIC, ACC_PRIVATE, ACC_STATIC, etc.)
192
* @return This builder instance
193
*/
194
public FieldInfoBuilder access(int flags);
195
196
/**
197
* Set field name
198
* @param name Field name
199
* @return This builder instance
200
*/
201
public FieldInfoBuilder name(String name);
202
203
/**
204
* Set field descriptor (type signature)
205
* @param descriptor Field descriptor (e.g., "I" for int, "Ljava/lang/String;" for String)
206
* @return This builder instance
207
*/
208
public FieldInfoBuilder descriptor(String descriptor);
209
210
/**
211
* Add field attributes
212
* @param attributes Array of field attributes
213
* @return This builder instance
214
*/
215
public FieldInfoBuilder attributes(Attribute... attributes);
216
217
/**
218
* Build the FieldInfo instance
219
* @return Complete FieldInfo
220
*/
221
public FieldInfo build();
222
}
223
```
224
225
### Method Builder
226
227
Create method information with bytecode and exception handling.
228
229
```java { .api }
230
/**
231
* Builder for creating MethodInfo instances
232
*/
233
public class MethodInfoBuilder {
234
/**
235
* Set method access flags
236
* @param flags Access flags (ACC_PUBLIC, ACC_PRIVATE, ACC_STATIC, etc.)
237
* @return This builder instance
238
*/
239
public MethodInfoBuilder access(int flags);
240
241
/**
242
* Set method name
243
* @param name Method name
244
* @return This builder instance
245
*/
246
public MethodInfoBuilder name(String name);
247
248
/**
249
* Set method descriptor (signature)
250
* @param descriptor Method descriptor (e.g., "()V" for void method with no parameters)
251
* @return This builder instance
252
*/
253
public MethodInfoBuilder descriptor(String descriptor);
254
255
/**
256
* Add method attributes (Code, Exceptions, etc.)
257
* @param attributes Array of method attributes
258
* @return This builder instance
259
*/
260
public MethodInfoBuilder attributes(Attribute... attributes);
261
262
/**
263
* Build the MethodInfo instance
264
* @return Complete MethodInfo
265
*/
266
public MethodInfo build();
267
}
268
```
269
270
### Attribute Builders
271
272
Create various class file attributes with proper validation.
273
274
```java { .api }
275
/**
276
* Builder for Code attribute containing method bytecode
277
*/
278
public class CodeAttributeBuilder {
279
/**
280
* Set maximum stack depth
281
* @param maxStack Maximum operand stack depth
282
* @return This builder instance
283
*/
284
public CodeAttributeBuilder max_stack(int maxStack);
285
286
/**
287
* Set maximum local variables
288
* @param maxLocals Maximum local variable slots
289
* @return This builder instance
290
*/
291
public CodeAttributeBuilder max_locals(int maxLocals);
292
293
/**
294
* Set the bytecode array
295
* @param code Method bytecode
296
* @return This builder instance
297
*/
298
public CodeAttributeBuilder code(byte[] code);
299
300
/**
301
* Add exception handlers
302
* @param handlers Array of exception handler information
303
* @return This builder instance
304
*/
305
public CodeAttributeBuilder exception_table(ExceptionHandler... handlers);
306
307
/**
308
* Add code attributes (LineNumberTable, LocalVariableTable, etc.)
309
* @param attributes Array of code attributes
310
* @return This builder instance
311
*/
312
public CodeAttributeBuilder attributes(Attribute... attributes);
313
314
/**
315
* Build the CodeAttribute
316
* @return Complete CodeAttribute
317
*/
318
public CodeAttribute build();
319
}
320
321
/**
322
* Builder for SourceFile attribute
323
*/
324
public class SourceFileAttributeBuilder {
325
/**
326
* Set the source filename
327
* @param filename Source file name
328
* @return This builder instance
329
*/
330
public SourceFileAttributeBuilder sourcefile(String filename);
331
332
/**
333
* Build the SourceFileAttribute
334
* @return Complete SourceFileAttribute
335
*/
336
public SourceFileAttribute build();
337
}
338
```
339
340
## Access Flag Constants
341
342
Standard Java access flags for classes, fields, and methods:
343
344
**Class Access Flags:**
345
- `ACC_PUBLIC` (0x0001) - Public class
346
- `ACC_FINAL` (0x0010) - Final class
347
- `ACC_SUPER` (0x0020) - Invoke super methods specially
348
- `ACC_INTERFACE` (0x0200) - Interface (not class)
349
- `ACC_ABSTRACT` (0x0400) - Abstract class
350
- `ACC_SYNTHETIC` (0x1000) - Generated by compiler
351
- `ACC_ANNOTATION` (0x2000) - Annotation type
352
- `ACC_ENUM` (0x4000) - Enum type
353
354
**Field Access Flags:**
355
- `ACC_PUBLIC` (0x0001) - Public field
356
- `ACC_PRIVATE` (0x0002) - Private field
357
- `ACC_PROTECTED` (0x0004) - Protected field
358
- `ACC_STATIC` (0x0008) - Static field
359
- `ACC_FINAL` (0x0010) - Final field
360
- `ACC_VOLATILE` (0x0040) - Volatile field
361
- `ACC_TRANSIENT` (0x0080) - Transient field
362
363
**Method Access Flags:**
364
- `ACC_PUBLIC` (0x0001) - Public method
365
- `ACC_PRIVATE` (0x0002) - Private method
366
- `ACC_PROTECTED` (0x0004) - Protected method
367
- `ACC_STATIC` (0x0008) - Static method
368
- `ACC_FINAL` (0x0010) - Final method
369
- `ACC_SYNCHRONIZED` (0x0020) - Synchronized method
370
- `ACC_BRIDGE` (0x0040) - Bridge method
371
- `ACC_VARARGS` (0x0080) - Variable argument method
372
- `ACC_NATIVE` (0x0100) - Native method
373
- `ACC_ABSTRACT` (0x0400) - Abstract method
374
375
## Complete Example
376
377
```java
378
import aQute.bnd.classfile.*;
379
import aQute.bnd.classfile.builder.*;
380
import static aQute.bnd.classfile.ClassFile.*;
381
382
// Create a complete class with methods and fields
383
MutableConstantPool pool = new MutableConstantPool();
384
385
// Build a simple class with a field and method
386
ClassFile classFile = new ClassFileBuilder()
387
.major_version(52) // Java 8
388
.minor_version(0)
389
.access(ACC_PUBLIC | ACC_SUPER)
390
.this_class("com/example/Calculator")
391
.super_class("java/lang/Object")
392
393
// Add a field: private int value;
394
.fields(new FieldInfoBuilder()
395
.access(ACC_PRIVATE)
396
.name("value")
397
.descriptor("I")
398
.build())
399
400
// Add a method: public int getValue()
401
.methods(new MethodInfoBuilder()
402
.access(ACC_PUBLIC)
403
.name("getValue")
404
.descriptor("()I")
405
.attributes(new CodeAttributeBuilder()
406
.max_stack(1)
407
.max_locals(1)
408
.code(new byte[] {
409
0x2A, // aload_0 (load this)
410
0x5F, // getfield
411
0x04, 0x00, // field reference index
412
0xAC // ireturn
413
})
414
.build())
415
.build())
416
417
.build();
418
419
// Write the class file
420
try (DataOutputStream out = new DataOutputStream(Files.newOutputStream(Paths.get("Calculator.class")))) {
421
classFile.write(out);
422
}
423
```