再コンパイル以外に、呼び出しを自分のものに rt.jar
置き換える方法はありますか?currentTimeMillis()
1# それを行う正しい方法は、Clock
オブジェクトと抽象的な時間を使用することです。
Clock
私はそれを知っていますが、実装していない、または独自の実装を作成した無数の開発者によって開発されたコードを実行することになります。
2# JMockit のようなモック ツールを使用して、そのクラスをモックします。
これはホットスポットが無効-Xint
になっている場合にのみ機能し、次のコードを使用して成功しましたが、外部ライブラリには「持続」しません。つまり、コードが制御できないため、どこでもモックする必要があるということです。以下のすべてのコードmain()
は (例のように) 0 ミリnew DateTime()
を返しますが、a は実際のシステム ミリを返します。
@MockClass(realClass = System.class)
public class SystemMock extends MockUp<System> {
// returns 1970-01-01
@Mock public static long currentTimeMillis() { return 0; }
}
System
3#を使用して起動時に再宣言する-Xbootclasspath/p
(編集済み)
可能であり、メソッドを作成/変更することはできますが、問題のメソッドは として宣言されていpublic static native long currentTimeMillis();
ます。Sun 独自のコードやネイティブコードを掘り下げずに宣言を変更することはできません。これにより、リバース エンジニアリングが行われ、安定したアプローチとは言えなくなります。最近のすべての SUN JVM が次のエラーでクラッシュします。
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00000, pid=4668, tid=5736
4# カスタム ClassLoader を使用する(コメントで提案されている新しいテスト)
JVMを使用してシステムCLを置き換えるのは簡単ですが-Djava.system.class.loader
、実際にはデフォルトのclassLoaderに頼るカスタムclassLoaderをロードし、システムはカスタムCLを通過することさえありません。
public class SimpleClassLoader extends ClassLoader {
public SimpleClassLoader(ClassLoader classLoader) {
super(classLoader);
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}
}
を使用してjava.lang.System
ロードされていることがわかりますrt.jar
java -verbose:class
Line 15: [Loaded java.lang.System from C:\jdk1.7.0_25\jre\lib\rt.jar]
オプションが不足しています。
私が見逃しているアプローチはありますか?