Spec-Zone.ru › OpenJDK 27

Класс Proxy

java.lang.Object
java.lang.reflect.Proxy
Все реализованные интерфейсы:
Serializable
public class Proxy extends Object implements Serializable
Proxy предоставляет статические методы для создания объектов, действующих подобно экземплярам интерфейсов, но позволяющих настраивать вызовы методов. Чтобы создать прокси-экземпляр для некоторого интерфейса Foo:
    InvocationHandler handler = new MyInvocationHandler(...);
    Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                         new Class<?>[] { Foo.class },
                                         handler);

Прокси-класс — это класс, создаваемый во время выполнения, который реализует указанный список интерфейсов, называемых прокси-интерфейсами. Прокси-экземпляр — это экземпляр прокси-класса. Каждый прокси-экземпляр имеет связанный объект обработчика вызовов, реализующий интерфейс InvocationHandler. Вызов метода на прокси-экземпляре через один из его прокси-интерфейсов будет перенаправлен в метод invoke обработчика вызовов этого экземпляра с передачей прокси-экземпляра, объекта java.lang.reflect.Method, идентифицирующего вызванный метод, и массива типа Object, содержащего аргументы. Обработчик вызовов обрабатывает закодированный вызов метода соответствующим образом, и возвращенный им результат возвращается в качестве результата вызова метода на прокси-экземпляре.

Прокси-класс обладает следующими свойствами:

  • Неполное имя прокси-класса не определено. Пространство имен классов, начинающихся со строки "$Proxy", тем не менее, должно быть зарезервировано для прокси-классов.
  • Пакет и модуль, в которых определен прокси-класс, указаны ниже.
  • Прокси-класс является final и неабстрактным.
  • Прокси-класс расширяет класс java.lang.reflect.Proxy.
  • Прокси-класс реализует в точности те интерфейсы, которые были указаны при его создании, и в том же порядке. Вызов getInterfaces для его объекта Class вернет массив, содержащий тот же список интерфейсов (в порядке, указанном при его создании), вызов getMethods для его объекта Class вернет массив объектов Method, включающий все методы этих интерфейсов, а вызов getMethod найдет методы в прокси-интерфейсах ожидаемым образом.
  • ProtectionDomain прокси-класса совпадает с доменом защиты системных классов, загруженных загрузчиком классов начальной загрузки, таких как java.lang.Object.
  • Метод Proxy.isProxyClass можно использовать для определения того, является ли указанный класс прокси-классом.

Прокси-экземпляр обладает следующими свойствами:

  • Для заданного прокси-экземпляра proxy и одного из интерфейсов Foo, реализованных его прокси-классом, следующее выражение вернет true:
        proxy instanceof Foo
    
    и следующая операция приведения типов завершится успешно (вместо того, чтобы выбросить ClassCastException):
        (Foo) proxy
    
  • Каждый прокси-экземпляр имеет связанный обработчик вызовов, переданный в его конструктор. Статический метод Proxy.getInvocationHandler возвращает обработчик вызовов, связанный с прокси-экземпляром, переданным в качестве аргумента.
  • Вызов метода интерфейса на прокси-экземпляре будет закодирован и перенаправлен в метод invoke обработчика вызовов, как описано в документации к этому методу.
  • Прокси-интерфейс может определять метод по умолчанию или наследовать его от своего суперинтерфейса прямо или косвенно. Обработчик вызовов может вызвать метод по умолчанию прокси-интерфейса путем вызова InvocationHandler::invokeDefault.
  • Вызов методов hashCode, equals или toString, объявленных в java.lang.Object, на прокси-экземпляре будет закодирован и перенаправлен в метод invoke обработчика вызовов точно так же, как кодируются и перенаправляются вызовы методов интерфейса, как описано выше. Классом объявления объекта Method, переданного в invoke, будет java.lang.Object. Другие открытые методы прокси-экземпляра, унаследованные от java.lang.Object, не переопределяются прокси-классом, поэтому вызовы этих методов ведут себя так же, как и для экземпляров класса java.lang.Object.

Принадлежность прокси-класса к пакету и модулю

Пакет и модуль, к которым принадлежит прокси-класс, выбираются таким образом, чтобы доступность прокси-класса соответствовала доступности прокси-интерфейсов. В частности, принадлежность к пакету и модулю прокси-класса, определенного с помощью методов getProxyClass(ClassLoader, Class[]) или newProxyInstance(ClassLoader, Class[], InvocationHandler), определяется следующим образом:
  1. Если все прокси-интерфейсы находятся в экспортируемых или открытых пакетах:
    1. если все прокси-интерфейсы являются public, то прокси-класс является public в безоговорочно экспортируемом, но неоткрытом пакете. Имя пакета и имя модуля не определены.
    2. если хотя бы один из всех прокси-интерфейсов является non-public, то прокси-класс является non-public в пакете и модуле непубличных интерфейсов. Все непубличные интерфейсы должны находиться в одном и том же пакете и модуле; в противном случае создание прокси для них невозможно.
  2. Если хотя бы один прокси-интерфейс находится в пакете, который является неэкспортируемым и неоткрытым:
    1. если все прокси-интерфейсы являются public, то прокси-класс является public в неэкспортируемом, неоткрытом пакете динамического модуля. Имена пакета и модуля не определены.
    2. если хотя бы один из всех прокси-интерфейсов является non-public, то прокси-класс является non-public в пакете и модуле непубличных интерфейсов. Все непубличные интерфейсы должны находиться в одном и том же пакете и модуле; в противном случае создание прокси для них невозможно.

Обратите внимание: если прокси-интерфейсы со смешанной доступностью — например, экспортируемый открытый интерфейс и неэкспортируемый непубличный интерфейс — проксируются одним и тем же экземпляром, то доступность прокси-класса определяется наименее доступным прокси-интерфейсом.

Обратите внимание, что произвольный код может получить доступ к прокси-классу в открытом пакете с помощью setAccessible, тогда как прокси-класс в неоткрытом пакете никогда не доступен коду вне модуля прокси-класса.

В этой спецификации под «неэкспортируемым пакетом» понимается пакет, который не экспортирован во все модули, а под «неоткрытым пакетом» — пакет, который не открыт для всех модулей. В частности, эти термины относятся к пакету, который либо не экспортирован/открыт содержащим его модулем, либо экспортирован/открыт содержащим его модулем с квалификацией.

Динамические модули

Динамический модуль — это именованный модуль, генерируемый во время выполнения. Прокси-класс, определенный в динамическом модуле, инкапсулирован и недоступен ни для одного модуля. Вызов Constructor.newInstance(Object...) для прокси-класса в динамическом модуле выбросит IllegalAccessException; вместо этого следует использовать метод Proxy.newProxyInstance.

Динамический модуль может читать модули всех суперинтерфейсов прокси-класса, а также модули классов и интерфейсов, на которые ссылаются все сигнатуры открытых методов прокси-класса. Если суперинтерфейс или упоминаемый класс/интерфейс, например T, находится в неэкспортируемом пакете, модуль класса/интерфейса T обновляется для экспорта пакета T в динамический модуль.

Методы, дублирующиеся в нескольких прокси-интерфейсах

Если два или более прокси-интерфейса содержат метод с одинаковым именем и сигнатурой параметров, порядок интерфейсов прокси-класса становится существенным. При вызове такого дублирующегося метода на прокси-экземпляре объект Method, переданный обработчику вызовов, не обязательно будет тем, чей класс объявления совместим по присваиванию с ссылочным типом интерфейса, через который был вызван метод прокси. Это ограничение существует потому, что соответствующая реализация метода в сгенерированном прокси-классе не может определить, через какой интерфейс она была вызвана. Поэтому при вызове дублирующегося метода на прокси-экземпляре объект Method для метода из самого первого интерфейса в списке интерфейсов прокси-класса, содержащего этот метод (напрямую или унаследованного через суперинтерфейс), передается в метод invoke обработчика вызовов независимо от ссылочного типа, через который произошел вызов метода.

Если прокси-интерфейс содержит метод с тем же именем и сигнатурой параметров, что и методы hashCode, equals или toString класса java.lang.Object, то при вызове такого метода на прокси-экземпляре объект Method, переданный обработчику вызовов, будет иметь java.lang.Object в качестве класса объявления. Иными словами, открытые не-final методы класса java.lang.Object логически предшествуют всем прокси-интерфейсам при определении того, какой объект Method передать обработчику вызовов.

Обратите внимание также, что при диспетчеризации дублирующегося метода в обработчик вызовов метод invoke может генерировать только проверяемые типы исключений, которые совместимы по присваиванию с одним из типов исключений в предложении throws метода во всех прокси-интерфейсах, через которые он может быть вызван. Если метод invoke выбрасывает проверяемое исключение, не совместимое по присваиванию ни с одним из типов исключений, объявленных методом в одном из прокси-интерфейсов, через которые он может быть вызван, то при вызове на прокси-экземпляре будет выброшено непроверяемое исключение UndeclaredThrowableException. Это ограничение означает, что не все типы исключений, возвращаемые вызовом getExceptionTypes для объекта Method, переданного в метод invoke, обязательно могут быть успешно выброшены методом invoke.

С версии:
1.3
См. также:
  • InvocationHandler
  • Сериализованная форма

Краткое описание полей

Модификатор и тип Поле Описание
protected InvocationHandler h
обработчик вызовов для этого прокси-экземпляра.

Краткое описание конструкторов

Proxy(InvocationHandler h)
Модификатор Конструктор Описание
protected
Создает новый экземпляр Proxy из подкласса (обычно динамического прокси-класса) с указанным значением для его обработчика вызовов.

Краткое описание методов

Модификатор и тип Метод Описание
static InvocationHandler getInvocationHandler(Object proxy)
Возвращает обработчик вызовов для указанного прокси-экземпляра.
static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
Устарело.
Прокси-классы, сгенерированные в именованном модуле, инкапсулированы и недоступны для кода вне своего модуля.
static boolean isProxyClass(Class<?> cl)
Возвращает true, если данный класс является прокси-классом.
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
Возвращает прокси-экземпляр для указанных интерфейсов, который диспетчеризирует вызовы методов указанному обработчику вызовов.

Методы, объявленные в классе Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Модификатор и тип Метод Описание
protected Object clone()
Создает и возвращает копию этого объекта.
boolean equals(Object obj)
Указывает, равен ли какой-либо другой объект этому объекту.
protected void finalize()
Устарело, для удаления: этот элемент API подлежит удалению в будущей версии.
Финализация устарела и подлежит удалению в будущем выпуске.
final Class<?> getClass()
Возвращает класс среды выполнения этого объекта Object.
int hashCode()
Возвращает значение хэш-кода для этого объекта.
final void notify()
Пробуждает один поток, ожидающий на мониторе этого объекта.
final void notifyAll()
Пробуждает все потоки, ожидающие на мониторе этого объекта.
String toString()
Возвращает строковое представление объекта.
final void wait()
Заставляет текущий поток ждать, пока он не будет разбужен, обычно посредством оповещения или прерывания.
final void wait(long timeoutMillis)
Заставляет текущий поток ожидать, пока он не будет пробужден, как правило, будучи оповещенным или прерванным, или пока не истечет определенное время.
final void wait(long timeoutMillis, int nanos)
Заставляет текущий поток ожидать, пока он не будет пробужден, как правило, будучи оповещенным или прерванным, или пока не истечет определенное время.

Подробное описание полей

h

protected InvocationHandler h
обработчик вызовов для этого прокси-экземпляра.

Подробное описание конструкторов

Proxy

protected Proxy(InvocationHandler h)
Создает новый экземпляр Proxy из подкласса (обычно динамического прокси-класса) с указанным значением для его обработчика вызовов.
Параметры:
h - обработчик вызовов для этого прокси-экземпляра
Исключения:
NullPointerException - если данный обработчик вызовов, h, равен null.

Подробное описание методов

getProxyClass

@Deprecated public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException
Устарело.
Прокси-классы, сгенерированные в именованном модуле, инкапсулированы и недоступны коду вне своего модуля. Constructor.newInstance выбросит IllegalAccessException при вызове для недоступного прокси-класса. Вместо этого используйте newProxyInstance(ClassLoader, Class[], InvocationHandler) для создания прокси-экземпляра.
Возвращает объект java.lang.Class для прокси-класса по заданному загрузчику классов и массиву интерфейсов. Прокси-класс будет определен указанным загрузчиком классов и будет реализовывать все предоставленные интерфейсы. Если какой-либо из указанных интерфейсов является непубличным, прокси-класс также будет непубличным. Если прокси-класс для той же комбинации интерфейсов уже был определен загрузчиком классов, будет возвращен существующий прокси-класс; в противном случае прокси-класс для этих интерфейсов будет динамически сгенерирован и определен загрузчиком классов.
Параметры:
loader - загрузчик классов для определения прокси-класса
interfaces - список интерфейсов, которые должен реализовать прокси-класс
Возвращает:
прокси-класс, определенный в указанном загрузчике классов и реализующий указанные интерфейсы
Исключения:
IllegalArgumentException - если нарушено любое из ограничений на параметры
NullPointerException - если аргумент массива interfaces или любой из его элементов равен null
См. также:
  • Принадлежность прокси-класса к пакету и модулю

newProxyInstance

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
Возвращает прокси-экземпляр для указанных интерфейсов, который диспетчеризирует вызовы методов указанному обработчику вызовов.

IllegalArgumentException будет выброшено при нарушении любого из следующих ограничений:

  • Все объекты Class в данном массиве interfaces должны представлять нескрытые и неселированные интерфейсы, а не классы или примитивные типы.
  • Никакие два элемента в массиве interfaces не могут ссылаться на идентичные объекты Class.
  • Все типы интерфейсов должны быть видимы по имени через указанный загрузчик классов. Иными словами, для загрузчика классов cl и каждого интерфейса i следующее выражение должно быть истинным:

    Class.forName(i.getName(), false, cl) == i

  • Все типы, на которые ссылаются все сигнатуры открытых методов указанных интерфейсов и типы, унаследованные их суперинтерфейсами, должны быть видимы по имени через указанный загрузчик классов.
  • Все непубличные интерфейсы должны находиться в одном и том же пакете и модуле, определенными указанным загрузчиком классов, а модуль непубличных интерфейсов должен иметь доступ ко всем типам интерфейсов; в противном случае реализация всех интерфейсов прокси-классом была бы невозможна независимо от того, в каком пакете он определен.
  • Для любого набора методов-членов указанных интерфейсов, имеющих одинаковую сигнатуру:
    • Если тип возвращаемого значения любого из методов является примитивным типом или void, то все эти методы должны иметь один и тот же тип возвращаемого значения.
    • В противном случае один из методов должен иметь тип возвращаемого значения, совместимый по присваиванию со всеми типами возвращаемых значений остальных методов.
  • Результирующий прокси-класс не должен превышать никаких ограничений, налагаемых виртуальной машиной на классы. Например, виртуальная машина может ограничивать количество интерфейсов, реализуемых классом, числом 65535; в этом случае размер массива interfaces не должен превышать 65535.

Обратите внимание, что порядок указанных прокси-интерфейсов имеет значение: два запроса на создание прокси-класса с одной и той же комбинацией интерфейсов, но в разном порядке, приведут к созданию двух разных прокси-классов.

Параметры:
loader - загрузчик классов для определения прокси-класса; может быть null для обозначения загрузчика классов начальной загрузки
interfaces - список интерфейсов, которые должен реализовать прокси-класс
h - обработчик вызовов, которому будут перенаправляться вызовы методов
Возвращает:
прокси-экземпляр с указанным обработчиком вызовов прокси-класса, определенного указанным загрузчиком классов и реализующего указанные интерфейсы
Исключения:
IllegalArgumentException - если нарушено любое из ограничений на параметры
NullPointerException - если аргумент массива interfaces или любой из его элементов равен null, либо если обработчик вызовов h равен null
См. также:
  • Принадлежность прокси-класса к пакету и модулю

isProxyClass

public static boolean isProxyClass(Class<?> cl)
Возвращает true, если данный класс является прокси-классом.
Примечание по реализации:
Надежность этого метода важна для возможности его использования при принятии решений безопасности, поэтому его реализация не должна просто проверять, расширяет ли рассматриваемый класс Proxy.
Параметры:
cl - проверяемый класс
Возвращает:
true, если класс является прокси-классом, и false в противном случае
Исключения:
NullPointerException - если cl равен null

getInvocationHandler

public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException
Возвращает обработчик вызовов для указанного прокси-экземпляра.
Параметры:
proxy - прокси-экземпляр, для которого необходимо вернуть обработчик вызовов
Возвращает:
обработчик вызовов для прокси-экземпляра
Исключения:
IllegalArgumentException - если аргумент не является прокси-экземпляром
NullPointerException - если proxy равен null

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в документации по Java SE, где содержатся более подробные описания, предназначенные для разработчиков, с концептуальными обзорами, определениями терминов, обходными путями и рабочими примерами кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком компании Oracle и/или ее дочерних предприятий в США и других странах.
Copyright © 1993, 2026, Oracle и/или ее дочерние предприятия, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API