Действительно ли возможно использовать instanceof при передаче объектов между Потоками?

Я столкнулся с проблемой, где instanceof работает, и затем он не делает. Сообщение подробности является трудным, но я думаю, что это могло бы быть проблемой:

Чтение этого: http://www.theserverside.com/news/thread.tss?thread_id=40229 (ищут Thread.currentThread), это, кажется, подразумевает, что, даже если два объекта являются тем же классом, если Вы передаете их между потоками с различными загрузчиками класса, instanceof (и isAssignableFrom) мог бы все еще перестать работать.

Это, конечно, объяснило бы поведение, которое я имею, но я задавался вопросом, мог ли кто-либо проверить его?

(Мне жаль, что статья, связанная в начале обсуждения, не была все еще доступна, но не кажется, что это.)

14
задан Qix 30 July 2016 в 07:18
поделиться

2 ответа

Это не имеет никакого отношения к потокам, только к загрузчикам классов. Одно и то же определение класса, загруженное разными загрузчиками классов, воспринимается JVM как два разных класса. Поэтому instanceof или приведение между ними не работают.

Итак, отвечая на ваш первоначальный вопрос: передача объектов между потоками, загруженными одним и тем же загрузчиком классов, безопасна, и 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

Так что все вроде бы сходится :-)

29
ответ дан 1 December 2019 в 09:00
поделиться

Проблема, как говорит Петер Торок, в загрузчиках классов. Кстати, это также причина того, что JNDI позволяет создавать общие объекты с помощью одного центрального загрузчика классов (это также означает, что нужные вам классы должны находиться в пути к классам единого центрального загрузчика классов, что доставляет массу удовольствия, когда вы нужно больше, чем просто струны).

1
ответ дан 1 December 2019 в 09:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: