Contents
Package org.cojen.maker
package org.cojen.maker
Dynamic Java class file generator. Here's a simple "hello, world" example:
Types and Values
The API supports many kinds of data types and values. To keep things simple, types
and values are passed as any kind of Types
The following kinds of types are supported:
A
Values
A value can be a Value type conversions
Automatic value type conversions are performed when setting variables or invoking methods:
Narrowing of primitive constants is performed automatically if no information would be lost
in the conversion. If the above example didn't have an explicit cast, passing the Thread safety
ClassMaker cm = ClassMaker.begin().public_();
// public static void run()...
MethodMaker mm = cm.addMethod(null, "run").public_().static_();
// System.out.println(...
mm.var(System.class).field("out").invoke("println", "hello, world");
Class<?> clazz = cm.finish();
clazz.getMethod("run").invoke(null);
Types and Values 
The API supports many kinds of data types and values. To keep things simple, types
and values are passed as any kind of Object
, but only a subset is allowed.
Types 
The following kinds of types are supported:
Type
— An explicit type object.Class
— Examples:int.class
,String.class
,int[].class
, etc.String
— Fully qualified class name or descriptor:"int"
,"java.lang.String"
,"int[]"
,"I"
,"Ljava/lang/String;"
,"[I"
, etc.ClassMaker
— Specifies the class being made.Variable
,Field
, orFieldMaker
— Specifies the type used by the givenVariable
orField
.null
— Specifies a context specific default such asvoid.class
.ClassDesc
— Specifies a type descriptor.
ClassMaker
. Unless explicitly specified, the actual name of the class being made isn't
known until it's finished.
ClassMaker cm = ...
MethodMaker factory = ...
// Pass the ClassMaker as the type to instantiate.
var instance = factory.new_(cm, ...);
...
factory.return_(instance)
Variable
can be used as a generic type carrier, and this won't actually allocate a variable slot.
MethodMaker mm = ...
var builderType = mm.var(StringBuilder.class);
var b1 = mm.new_(builderType, ...);
var b2 = mm.new_(builderType, ...);
...
Values 
A value can be a Variable
, a Field
or a constant:
- Primitive constant — Examples:
123
,true
, etc. - Boxed constant —
Integer
,Boolean
, etc. String
constantClass
constantEnum
constantMethodType
constantMethodHandleInfo
constantConstantDesc
constantConstable
constant
MethodHandleInfo
are treated specially when assigning them to
variables or parameters of type MethodHandle
. A lookup is performed at runtime which
resolves the MethodHandle instance. Handling of ConstantDesc
and Constable
is also treated specially — the actual type is determined by the resolved constant.
Constants that aren't in the above set can be specified via Variable.setExact
or Variable.condy
. The setExact
method
supports any kind of object, but this feature only works for classes which are directly
finished
. If the class is written to a file and then loaded from
it, the constant won't be found, resulting in a linkage error.
Value type conversions 
Automatic value type conversions are performed when setting variables or invoking methods:
- Widening — Example:
int
tolong
- Boxing — Example:
int
toInteger
- Widening and boxing — Example:
int
toLong
,Number
orObject
- Reboxing and widening — Example:
Integer
toLong
- Unboxing — Example:
Integer
toint
(NullPointerException
is possible) - Unboxing and widening — Example:
Integer
tolong
(NullPointerException
is possible)
int
cannot be automatically widened to float
, and long
cannot be
automatically widened to double
. For these cases, an explicit cast is required.
In addition, a calculation on a small primitive type doesn't automatically get converted to
int
:
// Make an unsigned conversion: int a = bytes[i] & 0xff;
// Without the cast, the 'and' operation only accepts a byte, and the result would be a byte.
var aVar = bytesVar.aget(iVar).cast(int.class).and(0xff);
0xff
constant to an operation which accepts a byte
would cause an exception to be
thrown at code generation time. This is because bytes are signed, and 0xff
is out
of bounds. A constant of -1
would be accepted, although it wouldn't correctly
perform an unsigned conversion.
Thread safety 
The classes which implement the interfaces in this package aren't designed to be
thread-safe. Only one thread at a time should be interacting with a ClassMaker
instance and any other objects that affect its state.
- See Also:
-
InterfacesClassDescriptionDefines the contents of an annotation.Represents an invoke dynamic bootstrap method which is bound to a
method
.Allows new classes and interfaces to be defined dynamically.Represents a field accessible by the body of amethod
.Allows new fields to be defined within a class.Represents a label bound to amethod
body.Base interface for making classes, methods, and fields.Allows new methods to be defined within a class.Describes a class which is being made, or describes an existing class or primitive type.Represents a variable bound to the body of amethod
.