14

instanceof が機能する問題に遭遇しましたが、機能しません。詳細に入るのは難しいですが、これが問題かもしれないと思います:

これを読む:http : //www.theserverside.com/news/thread.tss?thread_id=40229(Thread.currentThreadを検索)、2つのオブジェクトが同じクラスであっても、それらを渡すとそれを暗示しているようです異なるクラス ローダーを持つスレッド間では、instanceof (および isAssignableFrom) が引き続き失敗する可能性があります。

これは確かに私が持っている動作を説明するでしょうが、誰かがそれを確認できるかどうか疑問に思っていましたか?

(議論の最初にリンクされた記事がまだ利用可能であることを願っていますが、そうではないようです。)

4

2 に答える 2

30

これはスレッドとは関係なく、クラス ローダーのみに関係します。異なるクラスローダによってロードされた場合、同じクラス定義は、JVM によって 2 つの異なるクラスとして認識されます。Soinstanceofまたは 2 つの間のキャストは失敗します。

したがって、元の質問に答えるには、同じクラスローダーによってロードされたスレッド間でオブジェクトを渡すことは安全であり、instanceofその他. 正常に動作します。

クラスローディングの問題に関する記事はこちらです。

どのクラスローダーがゲーム内にあるかを確認する方法については、私の以前の回答も参照してください。

ロマンのコメントに更新

の動作をテストするためのコードを次に示しinstanceofます。

URL[] urls = new URL[] {new File("build/classes/").toURL()};
ClassLoader loader1 = new URLClassLoader(urls, null);
ClassLoader loader2 = new URLClassLoader(urls, null);
Class<?> c1 = loader1.loadClass("net.torokpeter.Foo");
Class<?> c2 = loader2.loadClass("net.torokpeter.Foo");
Object foo1 = c1.newInstance();
Object foo2 = c2.newInstance();

System.out.println("c1.toString(): " + c1);
System.out.println("c2.toString(): " + c2);
System.out.println("c1.equals(c2): " + c1.equals(c2));
System.out.println("c1 == c2: " + (c1 == c2));
System.out.println("foo1: " + foo1);
System.out.println("foo2: " + foo2);
System.out.println("foo1 instanceof Foo: " + (foo1 instanceof Foo));
System.out.println("foo2 instanceof Foo: " + (foo2 instanceof Foo));
System.out.println("c1.isAssignableFrom(c1): " + c1.isAssignableFrom(c1));
System.out.println("c2.isAssignableFrom(c2): " + c2.isAssignableFrom(c2));
System.out.println("c1.isAssignableFrom(c2): " + c1.isAssignableFrom(c2));
System.out.println("c2.isAssignableFrom(c1): " + c2.isAssignableFrom(c1));
System.out.println("c1.isAssignableFrom(Foo.class): " + c1.isAssignableFrom(Foo.class));
System.out.println("c2.isAssignableFrom(Foo.class): " + c2.isAssignableFrom(Foo.class));
System.out.println("Foo.class.isAssignableFrom(c1): " + Foo.class.isAssignableFrom(c1));
System.out.println("Foo.class.isAssignableFrom(c2): " + Foo.class.isAssignableFrom(c2));

出力は次のとおりです(Eclipse、Java5の場合):

c1.toString(): class net.torokpeter.Foo
c2.toString(): class net.torokpeter.Foo
c1.equals(c2): false
c1 == c2: false
foo1: net.torokpeter.Foo@360be0
foo2: net.torokpeter.Foo@45a877
foo1 instanceof Foo: false
foo2 instanceof Foo: false
c1.isAssignableFrom(c1): true
c2.isAssignableFrom(c2): true
c1.isAssignableFrom(c2): false
c2.isAssignableFrom(c1): false
c1.isAssignableFrom(Foo.class): false
c2.isAssignableFrom(Foo.class): false
Foo.class.isAssignableFrom(c1): false
Foo.class.isAssignableFrom(c2): false

したがって、すべてが一貫しているようです:-)

于 2010-06-11T20:47:50.027 に答える
1

問題は、Péter Török が言うように、クラスローダーにあります。ちなみに、これが JNDI の理由でもあり、共通オブジェクトを単一の中央クラスローダーによって作成できます (つまり、必要なクラスは単一の中央クラスローダーのクラスパスにある必要があり、あらゆる種類の楽しみを提供することも意味します)文字列以上のものを必要とします)。

于 2010-06-12T05:32:11.597 に答える