Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Dynamic Code Execution in Java Using Compiler API for Runtime Fixes

Tech 2

When production systems encounter unexpected issues, deploying a fix often requires going through a lengthy release cycle. To circumvent this, one approach is to allow dynamic execution of Java code at runtime via an HTTP endpoint. This technique leverages the Java Compiler API to compile and run user-provided source code on the fly.

The implementation described here supports:

  • Arbitrary SQL operations through MyBatis
  • Seamless integration with Spring’s dependency injection

Core Components

Tool and ToolProvider

Tool defines a standard interface for invoking command-line tools programmatically. Its run method executes the tool with specified I/O streams and arguments.

int run(InputStream in, OutputStream out, OutputStream err, String... args);

ToolProvider supplies system-level tools such as the Java compiler:

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

JavaCompiler Workflow

The JavaCompiler interface enables programmatic compilation. Key steps include:

  1. File Management: Use StandardJavaFileManager to manage source and class files.
  2. Compilation Task: Create a CompilationTask using getTask(), specifying output directory and source units.
  3. Diagnostics: Optionally attach a listener to capture compilation errors.

In-Memory Compilation

Instead of writing source files to disk, a custom JavaFileObject implementation holds source code in memory:

private static class InMemorySource extends SimpleJavaFileObject {
    private final String code;

    InMemorySource(String name, String code) {
        super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return code;
    }
}

Runtime Execution with Spring Integration

After successful compilation, the generated class is loaded using a URLClassLoader. The framework then:

  • Reflectively inspects constructor parameters
  • Resolves required dependencies from the Spring ApplicationContext
  • Instantiates the handler and invokes its handle() method

Fields annotated with @Ignore are excluded from dependency injection.

Handler Interface Contract

Uploaded code must implement a predefined interface:

public interface DynamicHandler {
    Object handle();
}

Universal Data Access Layer

A service class (DynamicDataManager) provides generic CRUD operations using MyBatis with dynamic SQL:

@Mapper
public interface DynamicDataMapper {
    @Update("UPDATE ${table} SET ${updates} WHERE ${condition}")
    void update(@Param("table") String table, 
                @Param("updates") String updates, 
                @Param("condition") String condition);

    @Select("SELECT ${columns} FROM ${table} WHERE ${condition}")
    List<Map<String, Object>> select(@Param("table") String table,
                                     @Param("columns") String columns,
                                     @Param("condition") String condition);
}

Result mapping converts database rows (snake_case) to POJO fields (camelCase), handling primitive and wrapper type conversions safely.

Example Usage

A sample handler updating an order record:

public class OrderFixHandler implements DynamicHandler {
    @Ignore
    private static final Logger logger = LoggerFactory.getLogger(OrderFixHandler.class);
    
    private final DynamicDataManager manager;

    public Object handle() {
        manager.update("t_order", "delivery_type=1, u_t=UNIX_TIMESTAMP()", "id=2381916717");
        return "Order updated successfully";
    }
}

This file is uploaded via a multipart POST request to /manual/allPowerful/go.

Security Warning: Allowing arbitrary code execution poses severe security risks. This mechanism should never be exposed in untrusted environments.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.