Hot Updating Java Apps with Groovy Metaclass and GroovyShell

This article demonstrates how to achieve Java hot‑update without rebuilding by leveraging Groovy's metaclass and GroovyShell, walking through a verification example, a full script implementation, and practical tips for handling script encoding issues.

FunTester
FunTester
FunTester
Hot Updating Java Apps with Groovy Metaclass and GroovyShell

The author explores using Groovy's metaClass feature to modify Java class behavior at runtime, enabling hot‑updates without a full rebuild. Building on earlier articles about Groovy dynamic methods and Arthas‑based Java hot‑update, the goal is to execute uploaded Groovy scripts that redefine methods on the fly.

Verification of Functionality

A simple class HotUpdate is created with a test() method that prints 123. In main, two instances are created; after the first call, the metaClass of HotUpdate is reassigned to output "FunTester". The second instance then reflects the new behavior.

package com.funtest.groovytest;

import com.funtester.frame.SourceCode;

class HotUpdate extends SourceCode {
    public static void main(String[] args) {
        def update = new HotUpdate();
        update.test();
        HotUpdate.metaClass.test = {output("FunTester")};
        def update2 = new HotUpdate();
        update2.test();
    }

    public void test() {
        output(123);
    }
}

Console output shows the original 123 followed by FunTester, confirming that the method was successfully overridden at runtime.

INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> main 
... (ASCII art omitted) ...
INFO-> main 123
INFO-> main FunTester
Process finished with exit code 0

Script‑Based Implementation

After confirming the concept, the author writes a Groovy script that performs the same metaClass reassignment. The script is executed via groovy.lang.GroovyShell using a helper class ExecuteGroovy. The full source combines imports, the original class, and a call to ExecuteGroovy.executeScript with the script string.

import com.funtester.frame.SourceCode;
import com.funtester.frame.execute.ExecuteGroovy;

class HotUpdate extends SourceCode {
    public static void main(String[] args) {
        def update = new HotUpdate();
        update.test();
        ExecuteGroovy.executeScript(
            "import com.funtest.groovytest.HotUpdate
" +
            "import com.funtester.frame.Output 
" +
            "
" +
            "HotUpdate.metaClass.test = {Output.output(\"FunTester\")}"
        );
        def update2 = new HotUpdate();
        update2.test();
    }

    public void test() {
        output(123);
    }
}

The resulting console output again shows 123 then FunTester, proving that the script‑driven hot‑update works.

INFO-> main 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> main 
... (ASCII art omitted) ...
INFO-> main 123
INFO-> main FunTester
Process finished with exit code 0

During script copying, IntelliJ may treat certain characters as escape sequences, causing mismatches between the intended script and the executed one. The author recommends avoiding direct copy‑paste of script strings; instead, upload script files or store them in an accessible Git repository for reliable execution.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaBackend DevelopmentGroovyHot UpdateMetaclassGroovyShell
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.