16

バイトコードを書き直してクラスをリロードすることで、その場でスレッドにフィールドを追加する方法を探していますが、それが可能かどうかはわかりません。どんなポインタも歓迎します。クラスの変更とロードに関する情報を見つけました.JRebelがコードをシームレスにホットスワップできることは知っていますが、同じアプローチ/ツールがここに適用されるかどうかはわかりません.

ここでの動機は、スレッド ローカル オブジェクトの理論的に優れた代替手段を探ることです。メソッドが機能する場合、スレッド ローカルをアノテーションに置き換えることができ、結果は現在の JDK 実装よりも優れているはずです。

追伸:「諸悪言論の根源」を救ってください

ユースケースの明確化:

ThreadLocal を持つクラスがあるとします。


class A {
   ThreadLocal<Counter> counter;
   ...
   counter.get().inc()
}

それを注釈に置き換えたい:


class A {
   @ThreadLocal
   Counter counter;
   ...
   counter.inc()
}

しかし、上記のコードが生成される代わりに、Thread が Acounter フィールドを持ち、実際のコードが次のようになるように Thread を変更したいと思います。


class A {
   // Nothing here, field is now in Thread
   ...
   Thread.currentThread().Acounter.inc()
}
4

8 に答える 8

11

現時点では、再定義によって新しいメソッドまたはフィールドが生成されるように、実行時にクラスを再定義することはできません。これは、既存のすべてのインスタンスのヒープをスキャンし、それらの変換 + それらの参照 + 潜在的な Unsafe フィールド オフセット ベース アップデーター (AtomicFieldUpdater など) に伴う複雑さによるものです。

この制限はJEP-159の一部として解除される可能性がありますが、concurrency-interest メーリング グループで議論されているように、これは大きな影響を与える変更であるため、まったく発生しない可能性があります。

Javaassist/similar を使用すると、クラスを新しいメソッド/フィールドを持つ新しいクラスに変換できます。このクラスは ClassLoader によってロードされ、実行時に使用できますが、その定義は既存のインスタンスを置き換えません。したがって、このメソッドをエージェントと組み合わせてクラスを再定義することはできません。インストルメンテーションの再定義は次のように制限されているためです。フィールド...」はこちらをご覧ください

だから今のところ、いいえ。

于 2013-06-18T07:06:48.040 に答える
5

JAR を動的にリロードするカスタム クラス ロード ソリューションを見てきClassLoaderました。JAR ファイルごとに 1 つ定義し、それを使用してその JAR からクラスをロードします。JAR 全体をリロードするには、そのClassLoaderインスタンスを「強制終了」して別のインスタンスを作成します (JAR ファイルを置き換えた後)。

を制御できないため、Java の内部Threadクラスをこのように微調整することはできないと思いますSystem ClassLoader。可能な解決策は、必要な変数でCustomThreadWeaver拡張された新しいクラスを生成するクラスを用意し、カスタムを使用してそれらをロードすることです。ThreadDynamicWeavedThreadClassLoader

頑張ってください。成功したらモンスターを見せてください;-)

于 2013-06-12T12:20:32.603 に答える
-2

あなたがやろうとしていることは不可能です。

ThreadLocal については既に知っているので、推奨される解決策が何であるかは既にわかっています。

あるいは、Thread をサブクラス化し、独自のフィールドを追加することもできます。ただし、そのクラスで明示的に作成したスレッドのみがこれらのフィールドを持つため、スレッド ローカルを使用するように "フォールバック" できる必要があります。

本当の問題は、「なぜスレッド ローカルが要件を満たしていないのか?」のように、「なぜ?」です。

于 2013-06-13T13:34:13.200 に答える