Установка переменных экземпляра прокси-объектов в 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 переменная. Увидеть:

Другие вопросы по тегам