Установка переменных экземпляра прокси-объектов в InvocationHandler
В объекте Proxy (объект, реализующий java.lang.reflect.InvocationHandler
), Я пытаюсь установить переменную экземпляра в объекте прокси.
Как следующее:
public class ServiceProxy implements InvocationHandler {
private final Object proxiedObject;
private ServiceProxy(final Object object) {
this.proxiedObject = object;
}
public static Object newInstance(final Object object) {
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new ServiceProxy(object));
}
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
Object result = null;
MyObject mo = new MyObject();
// Is the following safe when the proxiedObject is being acceessed by multiple threads?
final Field sessionField = this.proxiedObject.getClass().getSuperclass().getDeclaredField("mo");
sessionField.setAccessible(true);
sessionField.set(this.object, mo);
result = method.invoke(this.proxiedObject, args);
return result;
}
}
Это безопасно?
РЕДАКТИРОВАТЬ:
Актуальный код:
Object result = null;
Session session = HibernateUtil.getSessionFactory().getCurrentSession()
// Is the following save when the proxiedObject is being acceessed by multiple threads?
final Field sessionField = this.proxiedObject.getClass().getSuperclass().getDeclaredField("session");
sessionField.setAccessible(true);
sessionField.set(this.object, session);
result = method.invoke(this.proxiedObject, args);
return result;
Edit2: объект прокси вызывается из клиента GWT, который вызывает несколько методов одного и того же объекта прокси одновременно. Когда это происходит, я получаю, что поле экземпляра сеанса (прокси-класса) закрывается и открывается неожиданным образом.
1 ответ
Безопасно ли следующее, когда к объекту proxiedObject обращаются несколько потоков?
Нет, если mo
является volatile
, Если mo
поле volatile
тогда это будет должным образом пересекать барьер памяти и обновления к mo
поле увидят все темы.
Важно понимать, что если MyObject
не является неизменным, дополнительные проблемы параллелизма будут возникать, даже если mo
является volatile
,
Редактировать:
Спасибо @jtahlborn комментирует это. Я немного читал и теперь уверен, что volatile
также будет защищать MyObject
от частичной инициализации.
Из-за возможности изменения порядка инструкций конструктора нет гарантии, что MyObject
был заполнен, когда его ссылка распределяется между потоками. Только final
Поля в конструкторе гарантированно будут правильно инициализированы после завершения конструктора. Любые другие поля могут быть инициализированы или не инициализированы, поэтому вам нужно будет синхронизировать объект, прежде чем несколько потоков начнут получать к нему доступ.
Однако еслиmo
поле является изменчивым, то гарантия "произойдет раньше" также гарантирует, что MyObject
был полностью инициализирован. Компилятору не разрешается изменять порядок этих инструкций после публикации volatile
переменная. Увидеть: