DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Java 27 Makes G1 the Default Everywhere: How to Test Your Small Containers Before You Upgrade
  • Stop Writing Database Migration Scripts: Declarative Schema Sync for Java
  • Searching Kafka Without an Index: Lessons From Building Message Search for Kafdrop
  • ScyllaDB in Enterprise Java: High-Performance NoSQL With Eclipse JNoSQL

Trending

  • PWA on iOS, Part 2: HTTPS, Manifest and Service Worker
  • The Real Cost of Change in Software Development
  • Prompt Caching for LLMs, Part 1: Exact-Match Caching in Production
  • Tracing Dangerous Python Code Paths With rce-path

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Coding
  3. Java
  4. How to Generate and Compile Sources at Runtime in Java

How to Generate and Compile Sources at Runtime in Java

In this article, learn how to generate and compile sources at runtime in Java with and without class loading.

By 
Marion Keely
·
Feb. 03, 21 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
12.4K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

With ClassFactory, it is possible to generate classes at runtime, but how can we do that if we only need to compile sources without loading them or just generating sources?

Here come the source code generator components and the JavaMemoryCompiler of Burningwave Core to our aid. With source code generators, we can generate source code and store it on the drive or compile it via the JavaMemoryCompiler.

Now, let's try to generate and store the following class:

Java
 




x


 
1
package source.generation.test;
2

          
3
import java.util.Arrays;
4
import java.util.List;
5

          
6
public class MyClass {
7
    
8
    
9
    private List<String> words;
10
    
11
    public MyClass(String... words) {
12
        this.words = Arrays.asList(words);
13
    }
14
    
15
    public void print() {
16
        System.out.print(String.join(" ", words));
17
    }
18
    
19
    public static void main(String[] args) {
20
        new MyClass(args).print();
21
    }
22
}


With the source code generators:

Java
 




xxxxxxxxxx
1
60


 
1
package source.generation.test;
2

          
3
import java.lang.reflect.Modifier;
4
import java.util.Arrays;
5
import java.util.List;
6

          
7
import org.burningwave.core.classes.ClassSourceGenerator;
8
import org.burningwave.core.classes.FunctionSourceGenerator;
9
import org.burningwave.core.classes.GenericSourceGenerator;
10
import org.burningwave.core.classes.TypeDeclarationSourceGenerator;
11
import org.burningwave.core.classes.UnitSourceGenerator;
12
import org.burningwave.core.classes.VariableSourceGenerator;
13

          
14
public class SourceGenerationTester {
15

          
16
    
17
    public static UnitSourceGenerator generate() {
18
        return UnitSourceGenerator.create(SourceGenerationTester.class.getPackage().getName())
19
        .addClass(
20
            ClassSourceGenerator.create(TypeDeclarationSourceGenerator.create("MyClass"))
21
            .addField(
22
                VariableSourceGenerator.create(
23
                    TypeDeclarationSourceGenerator.create(List.class)
24
                    .addGeneric(GenericSourceGenerator.create(String.class)),
25
                    "words"
26
                )
27
            )
28
            .addConstructor(
29
                FunctionSourceGenerator.create().addParameter(
30
                    VariableSourceGenerator.create(
31
                        TypeDeclarationSourceGenerator.create(String.class)
32
                        .setAsVarArgs(true),
33
                        "words"
34
                    )
35
                ).addBodyCodeLine("this.words = Arrays.asList(words);").useType(Arrays.class)
36
            )
37
            .addMethod(
38
                FunctionSourceGenerator.create("print")
39
                .addModifier(Modifier.PUBLIC).setReturnType(void.class)
40
                .addBodyCodeLine(
41
                  "System.out.println(\"\\n\\t\" + String.join(\" \", words) + \"\\n\");"
42
                )
43
            )
44
            .addMethod(
45
                FunctionSourceGenerator.create("main")
46
                .addModifier(Modifier.PUBLIC | Modifier.STATIC)
47
                .setReturnType(void.class)
48
                .addParameter(VariableSourceGenerator.create(String[].class, "args"))
49
                .addBodyCodeLine("new MyClass(args).print();")
50
            )
51
        );
52
    }
53
    
54
    
55
    public static void main(String[] args) {
56
        UnitSourceGenerator unitSG = SourceGenerationTester.generate();
57
        unitSG.storeToClassPath(System.getProperty("user.home") + "/Desktop/sources");
58
        System.out.println("\nGenerated code:\n" + unitSG);
59
        
60
    }
61
}
62

          


And now let's try to compile the sources and store the compiled files with JavaMemoryCompiler:

Java
 




x
9
38


 
1
package source.compilation.test;
2

          
3

          
4
import org.burningwave.core.assembler.ComponentContainer;
5
import org.burningwave.core.classes.JavaMemoryCompiler;
6
import org.burningwave.core.classes.JavaMemoryCompiler.Compilation;
7
import org.burningwave.core.concurrent.QueuedTasksExecutor.ProducerTask;
8
import org.burningwave.core.io.FileSystemItem;
9

          
10
import source.generation.test.SourceGenerationTester;
11

          
12
public class SourceCompilationTester {
13
    
14
    
15
    public static void main(String[] args) throws ClassNotFoundException {
16
        ComponentContainer componentContainer = ComponentContainer.getInstance();
17
        JavaMemoryCompiler javaMemoryCompiler = componentContainer.getJavaMemoryCompiler();
18
        ProducerTask<Compilation.Result> compilationTask = javaMemoryCompiler.compile(
19
            Compilation.Config.forUnitSourceGenerator(
20
                SourceGenerationTester.generate()
21
            )
22
            .storeCompiledClassesTo(
23
                System.getProperty("user.home") + "/Desktop/classes"
24
            )
25
        );
26
        
27
        Compilation.Result compilationResult = compilationTask.join();
28
        
29
        System.out.println("\n\tAbsolute path of compiled file: " + 
30
            compilationResult.getClassPath()
31
            .findFirstInAllChildren(
32
                FileSystemItem.Criteria.forAllFileThat(FileSystemItem::isFile)
33
            ).getAbsolutePath() + "\n"
34
        );
35
    }
36
    
37
}


And now let's try to load the compiled file:

Java
 




xxxxxxxxxx
1
37


 
1
package source.compilation.test;
2

          
3
import static org.burningwave.core.assembler.StaticComponentContainer.ClassLoaders;
4
import static org.burningwave.core.assembler.StaticComponentContainer.Methods;
5

          
6
import org.burningwave.core.assembler.ComponentContainer;
7
import org.burningwave.core.classes.JavaMemoryCompiler;
8
import org.burningwave.core.classes.JavaMemoryCompiler.Compilation;
9
import org.burningwave.core.concurrent.QueuedTasksExecutor.ProducerTask;
10

          
11
import source.generation.test.SourceGenerationTester;
12

          
13
public class SourceCompilationTester {
14
    
15
    
16
    public static void main(String[] args) throws ClassNotFoundException {
17
        ComponentContainer componentContainer = ComponentContainer.getInstance();
18
        JavaMemoryCompiler javaMemoryCompiler = componentContainer.getJavaMemoryCompiler();
19
        ProducerTask<Compilation.Result> compilationTask = javaMemoryCompiler.compile(
20
            Compilation.Config.forUnitSourceGenerator(
21
                SourceGenerationTester.generate()
22
            )
23
            .storeCompiledClassesTo(
24
                System.getProperty("user.home") + "/Desktop/classes"
25
            )
26
        );
27
        
28
        Compilation.Result compilattionResult = compilationTask.join();
29
        
30
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
31
        ClassLoaders.addClassPaths(classLoader, compilattionResult.getDependencies());
32
        ClassLoaders.addClassPath(classLoader, compilattionResult.getClassPath().getAbsolutePath());
33
        Class<?> cls = classLoader.loadClass("source.generation.test.MyClass");
34
        Methods.invokeStaticDirect(cls, "main", new Object[] {new String[] {"Hello", "world!"}});
35
    }
36
    
37
}


Conclusion

In this tutorial, we learned how to generate and compile sources and how to load the generated class files. You can do a lot of things that are not mentioned here like, for example, compile sources that references classes located outside the runtime class paths. If you are curious or need further help, you can request it at the official forum.

Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Java 27 Makes G1 the Default Everywhere: How to Test Your Small Containers Before You Upgrade
  • Stop Writing Database Migration Scripts: Declarative Schema Sync for Java
  • Searching Kafka Without an Index: Lessons From Building Message Search for Kafdrop
  • ScyllaDB in Enterprise Java: High-Performance NoSQL With Eclipse JNoSQL

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook