スタックトレースとして FizzBuzz を出力

型エラーとして FizzBuzz を出力 - EAGLE 雑記」見て連想。
Javassistを使ってます。
Javassist直接使ったの初めてだけど、楽でいいなあ(ASMに比べて。)

package sample.fizzbuzz;

// depends on javassist-3.15.0
import javassist.*;

public class FizzBuzz {
    public void fizzBuzz(int n) throws Exception { // 面倒いのでごめん今回はException投げる
        ClassPool pool = ClassPool.getDefault();
        CtClass threadClass = pool.getCtClass(Thread.class.getName());
        
        CtClass $ = pool.makeClass("$", threadClass);
        
        CtMethod fizzMethod = CtNewMethod.make(
                "public void _Fizz(int n) {}", $);
        $.addMethod(fizzMethod);
        CtMethod buzzMethod = CtNewMethod.make(
                "public void _Buzz(int n) {}", $);
        $.addMethod(buzzMethod);
        CtMethod fizzBuzzMethod = CtNewMethod.make(
                "public void _FizzBuzz(int n) {}", $);
        $.addMethod(fizzBuzzMethod);

        CtMethod last = null;
        for (int i = 1; i <= n ; i++) {
            String invocationPart =
                last != null
                    ? String.format("%s($1 - 1);", last.getName())
                    : "throw new RuntimeException();";
            String withCondition =
                String.format("if ($1 == %d) {%s}", i, invocationPart);
            if (i % 15 == 0) {
                fizzBuzzMethod.insertAfter(withCondition);
                last = fizzBuzzMethod;
            } else if (i % 3 == 0) {
                fizzMethod.insertAfter(withCondition);
                last = fizzMethod;
            } else if (i % 5 == 0) {
                buzzMethod.insertAfter(withCondition);
                last = buzzMethod;
            } else {
                String src =
                    String.format("public void _%d(int n) {%s}", i, invocationPart);
                CtMethod numberMethod = CtNewMethod.make(src, $);
                $.addMethod(numberMethod);
                last = numberMethod;
            }
        }
        String invocationPart =
            last != null ? String.format("%s(%d);", last.getName(), n) : "";
        String src = String.format("public void run() {%s}", invocationPart);
        CtMethod runMethod = CtNewMethod.make(src, $);
        $.addMethod(runMethod);
        
        Class clazz = $.toClass();
        Thread fizzBuzz = (Thread) clazz.newInstance();
        fizzBuzz.start();
        fizzBuzz.join();
    }
    public static void main(String[] args) {
        try {
            new FizzBuzz().fizzBuzz(100);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

実行結果:

Exception in thread "Thread-0" java.lang.RuntimeException
        at $._1($.java)
        at $._2($.java)
        at $._Fizz($.java)
        at $._4($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._7($.java)
        at $._8($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $._11($.java)
        at $._Fizz($.java)
        at $._13($.java)
        at $._14($.java)
        at $._FizzBuzz($.java)
        at $._16($.java)
        at $._17($.java)
        at $._Fizz($.java)
        at $._19($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._22($.java)
        at $._23($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $._26($.java)
        at $._Fizz($.java)
        at $._28($.java)
        at $._29($.java)
        at $._FizzBuzz($.java)
        at $._31($.java)
        at $._32($.java)
        at $._Fizz($.java)
        at $._34($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._37($.java)
        at $._38($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $._41($.java)
        at $._Fizz($.java)
        at $._43($.java)
        at $._44($.java)
        at $._FizzBuzz($.java)
        at $._46($.java)
        at $._47($.java)
        at $._Fizz($.java)
        at $._49($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._52($.java)
        at $._53($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $._56($.java)
        at $._Fizz($.java)
        at $._58($.java)
        at $._59($.java)
        at $._FizzBuzz($.java)
        at $._61($.java)
        at $._62($.java)
        at $._Fizz($.java)
        at $._64($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._67($.java)
        at $._68($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $._71($.java)
        at $._Fizz($.java)
        at $._73($.java)
        at $._74($.java)
        at $._FizzBuzz($.java)
        at $._76($.java)
        at $._77($.java)
        at $._Fizz($.java)
        at $._79($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._82($.java)
        at $._83($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $._86($.java)
        at $._Fizz($.java)
        at $._88($.java)
        at $._89($.java)
        at $._FizzBuzz($.java)
        at $._91($.java)
        at $._92($.java)
        at $._Fizz($.java)
        at $._94($.java)
        at $._Buzz($.java)
        at $._Fizz($.java)
        at $._97($.java)
        at $._98($.java)
        at $._Fizz($.java)
        at $._Buzz($.java)
        at $.run($.java)