Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

機能概要

bytekinはJavaバイトコードを操作するためのいくつかの強力な変換機能を提供します。このセクションでは各機能の概要を説明します。

利用可能な機能

1. Inject - コードの挿入

ソースコードを変更せずに、メソッドの特定の箇所にカスタムコードを挿入します。

ユースケース:

  • ログステートメントの追加
  • 横断的関心事の実装
  • セキュリティチェックの追加
  • パラメータの検証

例:

@Inject(methodName = "calculate", methodDesc = "(II)I", at = At.HEAD)
public static CallbackInfo logStart(int a, int b) {
    System.out.println("Starting calculation");
    return CallbackInfo.empty();
}

詳細: Inject変換

2. Invoke - メソッド呼び出しのインターセプト

メソッド呼び出しをインターセプトし、必要に応じて引数や戻り値を変更します。

ユースケース:

  • 特定のメソッド呼び出しのインターセプト
  • メソッド引数の変更
  • メソッドのモックやスタブ化
  • 前処理/後処理の追加

例:

@Invoke(
    targetMethodName = "process",
    targetMethodDesc = "(Ljava/lang/String;)V",
    invokeMethodName = "validate",
    invokeMethodDesc = "(Ljava/lang/String;)V",
    shift = Shift.BEFORE
)
public static CallbackInfo validateBefore(String input) {
    return new CallbackInfo(false, null, new Object[]{input.trim()});
}

詳細: Invoke変換

3. Redirect - メソッド呼び出しのリダイレクト

実行時に呼び出されるメソッドを変更します。

ユースケース:

  • 代替実装への呼び出しのリダイレクト
  • メソッド動作のモック
  • メソッド転送の実装
  • 条件に基づく動作の変更

例:

@Redirect(
    targetMethodName = "oldMethod",
    targetMethodDesc = "(I)V",
    redirectMethodName = "newMethod",
    redirectMethodDesc = "(I)V"
)
public static void redirectCall(int value) {
    System.out.println("Redirected to new method: " + value);
}

詳細: Redirect変換

4. 定数の変更

バイトコードに埋め込まれた定数値を変更します。

ユースケース:

  • ハードコードされた設定値の変更
  • 文字列リテラルの変更
  • 数値定数の変更
  • 実行時の定数のパッチ

例:

@ModifyConstant(
    methodName = "getVersion",
    oldValue = "1.0",
    newValue = "2.0"
)
public static CallbackInfo updateVersion() {
    return CallbackInfo.empty();
}

詳細: 定数の変更

5. 変数の変更

メソッド内のローカル変数の値を変更します。

ユースケース:

  • 入力のサニタイゼーション
  • データの変換
  • 変数値のデバッグ
  • カスタムロジックの実装

例:

@ModifyVariable(
    methodName = "process",
    variableIndex = 1
)
public static void transformVariable(int original) {
    // 変換ロジック
}

詳細: 変数の変更

機能の組み合わせ

複雑な変換のために複数の機能を組み合わせて使用できます:

@ModifyClass("com.example.Service")
public class ServiceHooks {

    // ロギングのインジェクション
    @Inject(methodName = "handle", methodDesc = "(Ljava/lang/String;)V", at = At.HEAD)
    public static CallbackInfo logStart(String input) {
        System.out.println("Processing: " + input);
        return CallbackInfo.empty();
    }

    // 内部呼び出しのインターセプト
    @Invoke(
        targetMethodName = "handle",
        targetMethodDesc = "(Ljava/lang/String;)V",
        invokeMethodName = "validate",
        invokeMethodDesc = "(Ljava/lang/String;)V",
        shift = Shift.BEFORE
    )
    public static CallbackInfo validateInput(String input) {
        return new CallbackInfo(false, null, new Object[]{sanitize(input)});
    }

    private static String sanitize(String input) {
        return input.trim().toLowerCase();
    }
}

適切な機能の選択

機能目的複雑さ
Injectメソッドの特定箇所にコードを挿入
Invoke特定の呼び出しをインターセプト
Redirect呼び出し先を変更
定数の変更ハードコードされた値を変更
変数の変更ローカル変数を変換

次のステップ

  • Inject変換について学ぶ
  • Invokeインターセプトを探索する
  • を確認する