Two months after the primary commit in October 2022, Peter Verhas, Senior Architect at EPAM Methods, has launched model 2.0.0 of SourceBuddy, a brand new utility that compiles dynamically created Java supply code outlined by a String
or a file to a class
file. SourceBuddy, requiring Java 17, is a simplified facade for the javac
compiler, which delivers the identical performance.
Model 2.0.0 helps a mix of hidden and non-hidden lessons throughout compilation and run-time. Moreover, the API has been simplified, containing breaking modifications equivalent to altering the loadHidden()
methodology to the hidden()
methodology, therefore the brand new main launch. An entire overview of the modifications per model is on the market within the releases documentation on GitHub.
SourceBuddy can be utilized after including the next Maven dependency:
<dependency>
<groupId>com.javax0.sourcebuddy</groupId>
<artifactId>SourceBuddy</artifactId>
<model>2.0.0</model>
</dependency>
Alternatively the next Gradle dependency could also be used:
implementation 'com.javax0.sourcebuddy:SourceBuddy:2.0.0'
To reveal SourceBuddy, think about the next instance interface which can be utilized by the dynamically created code:
bundle com.app;
public interface PrintInterface {
void print();
}
The easy API is ready to compile one class at a time by utilizing the static com.javax0.sourcebuddy.Compiler.compile()
methodology. For instance, to compile a brand new class implementing the beforehand talked about PrintInterface
:
String supply = """
bundle com.app;
public class CustomClass implements PrintInterface {
@Override
public void print() {
System.out.println("Howdy world!");
}
}""";
Class<?> clazz = Compiler.compile(supply);
PrintInterface customClass =
(PrintInterface) clazz.getConstructor().newInstance();
customClass.print();
The fluent API presents options to unravel extra complicated issues such because the compilation of a number of recordsdata with the Compiler.java()
static methodology:
Compiler.java().from(supply).compile().load().newInstance(PrintInterface.class);
Optionally, the binary title of the category could also be specified, though SourceBuddy will already detect the title at any time when doable:
.from("com.app", supply)
For a number of supply recordsdata, the from()
methodology could also be referred to as a number of occasions, or all of the supply recordsdata in a particular listing could also be loaded without delay:
.from(Paths.get("src/major/java/sourcefiles"))
Optionally, the hidden()
methodology could also be used to create a Hidden Class which might’t be used straight by different lessons, solely via reflection by utilizing the category object returned by SourceBuddy.
The compile()
methodology generates the byte codes for the Java supply recordsdata, however does not load them into reminiscence but.
last var byteCodes = Compiler.java()
.from("com.app", supply)
.compile();
Optionally, the byte codes could also be saved to the native drive:
byteCodes.saveTo(Paths.get("./goal/generated_classes"));
Alternatively, the stream()
methodology, which returns a stream of byte arrays, could also be used to retrieve data such because the binary title:
byteCodes.stream().forEach(
bytecode -> System.out.println(Compiler.getBinaryName(bytecode)));
The byteCodes.load()
methodology masses the lessons and converts the bytecode to Class
objects:
last var loadedClasses = compiled.load();
Accessing a category is feasible by casting to a superclass or an interface the category implements or by utilizing the reflection API. For instance, to entry the CustomClass
:
Class<?> customClass = loadedClasses.get("com.app.CustomClass");
Alternatively, the newInstance()
methodology could also be used to create an occasion of the category:
Object customClassInstance = loadedClasses.newInstance("com.app.CustomClass");
The stream of lessons could also be used to retrieve extra details about the lessons:
loadedClasses.stream().forEach(
clazz -> System.out.println(clazz.getSimpleName()));
Extra details about SourceBuddy may be discovered within the detailed explanations contained in the README
file on GitHub.