Java でメソッドを静的にディスパッチする

普通にReflectionを使っても無理。

基本となるメソッドがインスタンスメソッドの場合、動的メソッドルックアップを使用して呼び出しが行われ、ターゲットオブジェクトの実行時の型に基づいてオーバーライドが実行されます (『Java 言語仕様第 2 版』のセクション 15.12.4.4 を参照)。

要するに呼び出したい Class に対して getMethod で Method オブジェクトを取得しようがインスタンスメソッドは invoke を呼び出した時点で動的にディスパッチされてしまう。
が、言語仕様を確認するとこうある。

メソッド検索のための戦略は,呼出しのモードに依存する。
もし呼出しのモードが static であるならば,ターゲットの参照は必要なく,上書きも許されない。 クラス T のメソッド m が呼び出されるメソッドになる。
そうでなければ,インスタンスメソッドが呼び出され,ターゲットの参照が存在する。 もしターゲット参照が null であるならば,この時点で NullPointerException が投げられる。 そうでなければ,そのターゲットの参照は ターゲットオブジェクト (target object) を参照すると言い,及び呼び出されたメソッドで this キーワードの値として使用される。 呼出しのモードのための他の四つの可能性を検討する。
もし呼出しのモードが nonvirtual であるならば, 上書きは許されない。 クラス T のメソッド m が呼び出されるべきとする。
そうでなければ,呼出しのモードは interface,virtual 又は super のいずれかになり,上書きされるかもしれない。 その場合,動的なメソッド検索 (dynamic method lookup) が使用される。 動的な検索の過程はクラス S から開始され,次のように決定される。

つまり nonvirtual なモードであればいい。15.12.3節にあるとおり private なインスタンスメソッドは nonvirtual になる(private メソッドが動的にディスパッチされても困るし)。
ということで、結論としてはこんなの。

import java.lang.reflect.Method;

class B {
    @SuppressWarnings("unused")
    private void method() {
        System.out.println("B#method");
    }
}

class D extends B {
    @SuppressWarnings("unused")
    private void method() {
        System.out.println("D#method");
    }
}

public class MethodTest {
    public static void main(String[] args) throws Exception {
        B a = new D();
        Method method = B.class.getDeclaredMethod("method", new Class[0]);
        method.setAccessible(true);
        System.out.println(method.getDeclaringClass());
        method.invoke(a, new Object[0]);
    }
}

まぁ、もともと静的にディスパッチされているものを Reflection 使って、やっぱり静的にディスパッチしているわけで、あんまり面白くないというか、当初の目的と違う気がする。
ASMJavassist なんかの bytecode manipulation framework を使えば無理矢理できそうな気がしないでもないが、Java の仕様を見る限り、代わりに普通にメソッドコールしても動的ディスパッチできなくなるというオチが待ってそう。