Класс MethodHandles.Lookup
- java.lang.Object
-
- java.lang.invoke.MethodHandles.Lookup
- Вложенный класс:
- MethodHandles
public static final class MethodHandles.Lookup extends Object
Объект поиска — это фабрика для создания обработчиков методов, когда для создания требуется проверка доступа. Обработчики методов не выполняют проверок доступа при вызове, а только при создании. Поэтому ограничения доступа к обработчикам методов должны применяться при их создании. Класс вызывающего, против которого применяются эти ограничения, известен как класс поиска.
Класс поиска, которому необходимо создать обработчики методов, вызовет MethodHandles.lookup, чтобы создать для себя фабрику. При создании объекта-фабрики Lookup определяется и безопасно сохраняется идентификатор класса поиска в объекте Lookup. Затем класс поиска (или его делегаты) могут использовать методы фабрики в объекте Lookup для создания обработчиков методов для членов, доступ к которым проверяется. Это включает все методы, конструкторы и поля, разрешённые для класса поиска, даже приватные.
Методы фабрики поиска
Методы фабрики объектаLookup соответствуют всем основным случаям использования методов, конструкторов и полей. Каждый обработчик метода, созданный методом фабрики, функционально эквивалентен определённому поведению байткода. (Поведение байткода описано в разделе 5.4.3.5 спецификации Java Virtual Machine.) Вот сводка соответствия между этими методами фабрики и поведением полученных обработчиков методов: | выражение поиска | член | поведение байткода |
|---|---|---|
lookup.findGetter(C.class,"f",FT.class) | FT f; |
(T) this.f; |
lookup.findStaticGetter(C.class,"f",FT.class) |
staticFT f;
|
(T) C.f; |
lookup.findSetter(C.class,"f",FT.class) | FT f; |
this.f = x; |
lookup.findStaticSetter(C.class,"f",FT.class) |
staticFT f;
|
C.f = arg; |
lookup.findVirtual(C.class,"m",MT) | T m(A*); |
(T) this.m(arg*); |
lookup.findStatic(C.class,"m",MT) |
staticT m(A*);
|
(T) C.m(arg*); |
lookup.findSpecial(C.class,"m",MT,this.class) | T m(A*); |
(T) super.m(arg*); |
lookup.findConstructor(C.class,MT) | C(A*); |
new C(arg*); |
lookup.unreflectGetter(aField) | (static)?FT f;
|
(FT) aField.get(thisOrNull); |
lookup.unreflectSetter(aField) | (static)?FT f;
|
aField.set(thisOrNull, arg); |
lookup.unreflect(aMethod) | (static)?T m(A*);
|
(T) aMethod.invoke(thisOrNull, arg*); |
lookup.unreflectConstructor(aConstructor) | C(A*); |
(C) aConstructor.newInstance(arg*); |
lookup.unreflect(aMethod) | (static)?T m(A*);
|
(T) aMethod.invoke(thisOrNull, arg*); |
lookup.findClass("C") | class C { ... } |
C.class; |
C — это класс или интерфейс, в котором ищется член, документированный как параметр с именем refc в методах поиска. Тип метода MT составлен из возвращаемого типа T и последовательности типов аргументов A*. Конструктор также имеет последовательность типов аргументов A* и считается возвращающим новый созданный объект типа C. И MT, и тип поля FT документированы как параметр с именем type. Формальный параметр this представляет ссылку на себя типа C; если он присутствует, он всегда является ведущим аргументом для вызова обработчика метода. (В случае некоторых protected членов this может быть ограничен по типу классом поиска; см. ниже.) Название arg обозначает все остальные аргументы обработчика метода. В примерах кода для API основного отражения имя thisOrNull обозначает нулевую ссылку, если доступный метод или поле статические, и this в противном случае. Имена aMethod, aField, и aConstructor обозначают рефлексивные объекты, соответствующие заданным членам. Поведение байткода для операции findClass — это загрузка константного класса, как если бы это было выполнено с помощью ldc CONSTANT_Class. Это поведение представлено не как обработчик метода, а непосредственно как константа Class.
В тех случаях, когда заданный член имеет переменную арность (т.е. метод или конструктор), возвращаемый обработчик метода также будет иметь переменную арность. Во всех других случаях возвращаемый обработчик метода будет иметь фиксированную арность.
Обсуждение: Эквивалентность между обработчиками методов поиска и подлежащими членами классов и поведением байткода может нарушиться несколькими способами:
- Если
Cне доступен символически из загрузчика класса поиска, поиск всё ещё может быть успешным, даже если нет эквивалентного выражения Java или байткодовой константы. - Точно так же, если
TилиMTнедоступны символически из загрузчика класса поиска, поиск все еще может быть успешным. Например, поискMethodHandle.invokeExactиMethodHandle.invokeвсегда будет успешным, независимо от запрошенного типа. - Если установлен менеджер безопасности, он может запретить поиск по различным причинам (см. ниже). В отличие от этого, инструкция
ldcдля константыCONSTANT_MethodHandleне подвергается проверкам менеджером безопасности. - Если искомый метод имеет очень большую арность, создание обработчика метода может завершиться неудачей из-за того, что у типа обработчика метода слишком много параметров.
Проверка доступа
Проверки доступа применяются в методах фабрикиLookup, когда создаётся обработчик метода. Это ключевое различие с API основного отражения, так как java.lang.reflect.Method.invoke выполняет проверку доступа для каждого вызывающего по каждому вызову. Все проверки доступа начинаются с объекта Lookup, который сравнивает свой записанный класс поиска со всеми запросами на создание обработчиков методов. Один объект Lookup может использоваться для создания любого количества обработчиков методов с проверкой доступа, все они проверяются по одному классу поиска.
Объект Lookup может быть общим для другого надёжного кода, такого как метаобъектный протокол. Общий объект Lookup делегирует способность создавать обработчики методов для приватных членов класса поиска. Даже если привилегированный код использует объект Lookup, проверка доступа ограничена привилегиями исходного класса поиска.
Поиск может завершиться неудачей, потому что содержащий класс недоступен для класса поиска, или потому, что нужный член класса отсутствует, или потому, что нужный член класса недоступен для класса поиска, или потому, что объект поиска недостаточно надёжен для доступа к члену. В любом из этих случаев будет выброшено исключение ReflectiveOperationException при попытке поиска. Точный класс будет одним из следующих:
- NoSuchMethodException — если запрашивается метод, но он не существует
- NoSuchFieldException — если запрашивается поле, но оно не существует
- IllegalAccessException — если член существует, но проверка доступа завершается неудачей
В общем случае условия, при которых обработчик метода может быть найден для метода M, не более ограничительные, чем условия, при которых класс поиска мог бы скомпилировать, проверить и разрешить вызов M. Там, где JVM выбросила бы исключения, такие как NoSuchMethodError, поиск обработчика метода, как правило, выбросит соответствующее проверенное исключение, такое как NoSuchMethodException. И эффект вызова обработчика метода, полученного в результате поиска, точно эквивалентен выполнению скомпилированного, проверенного и разрешенного вызова M. Такая же точка справедлива для полей и конструкторов.
Обсуждение: Проверки доступа применяются только к именованным и отражённым методам, конструкторам и полям. Другие методы создания обработчиков методов, такие как MethodHandle.asType, не требуют проверок доступа и используются независимо от любого объекта Lookup.
Если желаемый член protected, применяются обычные правила JVM, включая требование, чтобы класс поиска находился либо в том же пакете, что и желаемый член, либо наследовал этот член. (См. спецификацию Java Virtual Machine, разделы 4.9.2, 5.4.3.5 и 6.4.) Кроме того, если желаемый член — это нестатическое поле или метод в другом пакете, полученный обработчик метода может быть применён только к объектам класса поиска или одного из его подклассов. Это требование обеспечивается сужением типа ведущего параметра this от C (который обязательно будет суперклассом класса поиска) до самого класса поиска.
JVM накладывает аналогичное требование на инструкцию invokespecial, что аргумент получателя должен соответствовать как разрешённому методу, так и текущему классу. Опять же, это требование обеспечивается сужением типа ведущего параметра результата обработчика метода. (См. спецификацию Java Virtual Machine, раздел 4.10.1.9.)
JVM представляет конструкторы и блоки статической инициализации как внутренние методы со специальными именами ("<init>" и "<clinit>"). Внутренний синтаксис команд вызова позволяет обращаться к таким внутренним методам, как к обычным методам, но виртуальная машина Java отклоняет их. Поиск такого внутреннего метода вернёт NoSuchMethodException.
Если связь между вложенными типами выражается непосредственно через атрибуты NestHost и NestMembers (см. спецификацию виртуальной машины Java, разделы 4.7.28 и 4.7.29), то связанный объект Lookup предоставляет прямой доступ к классу поиска и всем его вложенным классам (см. Class.getNestHost). В противном случае доступ между вложенными классами осуществляется путём создания компилятором Java оберточного метода для доступа к частному методу другого класса в том же вложении. Например, вложенный класс C.D может получить доступ к частным членам других связанных классов, таких как C, C.D.E или C.B, но компилятор Java может потребоваться сгенерировать оберточные методы в этих связанных классах. В таких случаях объект Lookup в C.E не сможет получить доступ к этим частным членам. Решение этой проблемы — метод Lookup.in, который может преобразовать поиск в C.E в поиск в любом из этих других классов без специального повышения привилегий.
Доступ, разрешённый данному объекту поиска, может быть ограничен, в соответствии с набором lookupModes, подмножеством членов, обычно доступных для класса поиска. Например, метод publicLookup создаёт объект поиска, который может получить доступ только к общедоступным членам в общедоступных классах экспортированных пакетов. Метод lookup, чувствительный к вызывающему объекту, создаёт объект поиска с полными возможностями относительно класса вызывающего объекта, чтобы эмулировать все поддерживаемые поведения байткода. Также метод Lookup.in может создать объект поиска с меньшим набором режимов доступа, чем исходный объект поиска.
Обсуждение доступа по умолчанию: Мы говорим, что поиск имеет доступ по умолчанию, если его режимы доступа включают возможность доступа к private членам (что включает частные члены связанных классов). Как документировано в соответствующих методах в других местах, только поиски с доступом по умолчанию обладают следующими возможностями:
- доступ к частным полям, методам и конструкторам класса поиска и его вложенных классов
- создание хэндлов методов, которые вызывают методы, чувствительные к вызывающему объекту, такие как
Class.forName - создание хэндлов методов, которые
emulate invokespecialинструкции - обход проверок доступа к пакету для классов, доступных для класса поиска
- создание
delegated lookup objects, которые имеют доступ по умолчанию к другим классам в том же члене пакета
Каждое из этих разрешений является следствием того, что объект поиска с доступом по умолчанию может быть безопасно прослежен до исходного класса, чьи поведения байткода и разрешения доступа языка Java могут быть надёжно определены и эмулированы хэндлами методов.
Взаимодействие с менеджером безопасности
Хотя инструкции байткода могут ссылаться только на классы в связанном загрузчике классов, этот API может искать методы в любом классе, если доступен ссылка на егоClass объект. Такие ссылки между загрузчиками классов также возможны с API ядра рефлексии и невозможны для инструкций байткода, таких как invokestatic или getfield. Существует API менеджера безопасности, чтобы приложения могли проверять такие ссылки между загрузчиками классов. Эти проверки применимы как к API MethodHandles.Lookup, так и к API ядра рефлексии (как и в Class). Если менеджер безопасности присутствует, поиск членов и классов подвергается дополнительным проверкам. Вызываются от одного до трёх методов менеджера безопасности. Любой из этих методов может отказать в доступе, выбросив исключение SecurityException. Определим smgr как менеджер безопасности, lookc как класс поиска текущего объекта поиска, refc как содержащий класс, в котором ищется член, и defc как класс, в котором фактически определён член. (Если к классу или другому типу осуществляется доступ, значения refc и defc являются самим классом.) Значение lookc определяется как отсутствующее, если у текущего объекта поиска нет доступа по умолчанию. Вызовы выполняются в соответствии со следующими правилами:
-
Шаг 1: Если
lookcотсутствует или его загрузчик классов не совпадает с загрузчиком классовrefcили его предком, то вызываетсяsmgr.checkPackageAccess(refcPkg), гдеrefcPkg— пакетrefc. -
Шаг 2а: Если полученный член не общедоступен и
lookcотсутствует, то вызываетсяsmgr.checkPermissionсRuntimePermission("accessDeclaredMembers"). -
Шаг 2b: Если у полученного класса есть загрузчик классов
null, иlookcотсутствует, то вызываетсяsmgr.checkPermissionсRuntimePermission("getClassLoader"). -
Шаг 3: Если полученный член не общедоступен, и
lookcотсутствует, иdefcиrefcразличны, то вызываетсяsmgr.checkPackageAccess(defcPkg), гдеdefcPkg— пакетdefc.
Методы, чувствительные к вызывающему объекту
Небольшое количество методов Java обладает специальным свойством, называемым чувствительностью к вызывающему объекту. Метод, чувствительный к вызывающему объекту, может вести себя по-разному в зависимости от идентификатора своего непосредственного вызывающего объекта.Если запрашивается хэндл метода, чувствительный к вызывающему объекту, то применяются общие правила поведений байткода, но они учитывают класс поиска особым образом. Результирующий хэндл метода ведёт себя так, как будто он был вызван из инструкции, содержащейся в классе поиска, чтобы метод, чувствительный к вызывающему объекту, определил класс поиска. (При этом вызывающий объект хэндла метода игнорируется.) Таким образом, в случае методов, чувствительных к вызывающему объекту, разные классы поиска могут привести к поведению хэндлов методов.
В случаях, когда объект поиска является publicLookup() или каким-либо другим объектом поиска без доступа по умолчанию, класс поиска игнорируется. В таких случаях хэндл метода, чувствительный к вызывающему объекту, создать нельзя, доступ запрещён, и поиск завершается с IllegalAccessException.
Обсуждение: Например, метод, чувствительный к вызывающему объекту, Class.forName(x), может возвращать разные классы или выбрасывать разные исключения в зависимости от загрузчика классов класса, который его вызывает. Общедоступный поиск Class.forName завершится ошибкой, так как нет разумного способа определить его поведение байткода.
Если приложение кэширует хэндлы методов для широкого совместного использования, то для их создания следует использовать publicLookup(). Если произойдёт поиск Class.forName, поиск завершится неудачей, и приложение должно предпринять соответствующие действия в этом случае. Возможно, более поздний поиск, например, во время вызова метода инициализации, сможет включить специфический идентификатор вызывающего объекта, сделав метод доступным.
Функция MethodHandles.lookup чувствительна к вызывающему объекту, чтобы создать надёжную основу для поиска. Почти все другие методы API JSR 292 полагаются на объекты поиска для проверки запросов доступа.
Поля
| Модификатор и тип | Поле | Описание |
|---|---|---|
static int | MODULE | Маска из одного бита, представляющая доступ по умолчанию (доступ по умолчанию), которая может повлиять на результат |
static int | PACKAGE | Маска из одного бита, представляющая доступ по умолчанию (доступ по умолчанию), которая может повлиять на результат |
static int | PRIVATE | Маска из одного бита, представляющая доступ по умолчанию, которая может повлиять на результат |
static int | PROTECTED | Маска из одного бита, представляющая доступ по умолчанию, которая может повлиять на результат |
static int | PUBLIC | Маска из одного бита, представляющая доступ по умолчанию, которая может повлиять на результат |
static int | UNCONDITIONAL | Маска из одного бита, представляющая доступ по умолчанию, которая может повлиять на результат |
Методы
| Модификатор и тип | Метод | Описание |
|---|---|---|
Class<?> | accessClass(Class<?> targetClass) | Определяет, может ли класс быть доступен из контекста поиска, определенного этим объектом |
MethodHandle | bind(Object receiver,
String name,
MethodType type) | Создает метод-обработчик ранней привязки для нестатического метода. |
Class<?> | defineClass(byte[] bytes) | Определяет класс в том же загрузчике классов, в том же пакете выполнения и в той же области защиты домена защиты, что и класс поиска этого поиска. |
MethodHandles.Lookup | dropLookupMode(int modeToDrop) | Создаёт поиск в том же классе поиска, что и текущий объект поиска, который находит члены, но с режимом поиска, который потерял заданный режим поиска. |
Class<?> | findClass(String targetName) | Ищет класс по имени в контексте поиска, определенном этим объектом |
MethodHandle | findConstructor(Class<?> refc,
MethodType type) | Создаёт метод-обработчик, который создаёт объект и инициализирует его, используя конструктор указанного типа. |
MethodHandle | findGetter(Class<?> refc,
String name,
Class<?> type) | Создаёт метод-обработчик, предоставляющий доступ для чтения к нестатическому полю. |
MethodHandle | findSetter(Class<?> refc,
String name,
Class<?> type) | Создаёт метод-обработчик, предоставляющий доступ для записи к нестатическому полю. |
MethodHandle | findSpecial(Class<?> refc,
String name,
MethodType type,
Class<?> specialCaller) | Создаёт метод-обработчик ранней привязки для виртуального метода. |
MethodHandle | findStatic(Class<?> refc,
String name,
MethodType type) | Создаёт метод-обработчик для статического метода. |
MethodHandle | findStaticGetter(Class<?> refc,
String name,
Class<?> type) | Создаёт метод-обработчик, предоставляющий доступ для чтения к статическому полю. |
MethodHandle | findStaticSetter(Class<?> refc,
String name,
Class<?> type) | Создаёт метод-обработчик, предоставляющий доступ для записи к статическому полю. |
VarHandle | findStaticVarHandle(Class<?> decl,
String name,
Class<?> type) | Создаёт VarHandle, предоставляющий доступ к статическому полю |
VarHandle | findVarHandle(Class<?> recv,
String name,
Class<?> type) | Создаёт VarHandle, предоставляющий доступ к нестатическому полю |
MethodHandle | findVirtual(Class<?> refc,
String name,
MethodType type) | Создаёт метод-обработчик для виртуального метода. |
boolean | hasPrivateAccess() | Возвращает |
MethodHandles.Lookup | in(Class<?> requestedLookupClass) | Создаёт поиск в указанном новом классе поиска. |
Class<?> | lookupClass() | Указывает, какой класс выполняет поиск. |
int | lookupModes() | Указывает, какие классы защиты доступа к членам может создавать этот объект поиска. |
MethodHandleInfo | revealDirect(MethodHandle target) | Расшифровывает прямой метод-обработчик, созданный этим объектом поиска или подобным ему. |
String | toString() | Отображает имя класса, из которого должны производиться поиски. |
MethodHandle | unreflect(Method m) | Создаёт прямой метод-обработчик для m, если класс поиска имеет разрешение. |
MethodHandle | unreflectConstructor(Constructor<?> c) | Создаёт метод-обработчик для отражённого конструктора. |
MethodHandle | unreflectGetter(Field f) | Создаёт метод-обработчик, предоставляющий доступ для чтения к отражённому полю. |
MethodHandle | unreflectSetter(Field f) | Создаёт метод-обработчик, предоставляющий доступ для записи к отражённому полю. |
MethodHandle | unreflectSpecial(Method m,
Class<?> specialCaller) | Создаёт метод-обработчик для отражённого метода. |
VarHandle | unreflectVarHandle(Field f) | Создаёт VarHandle, предоставляющий доступ к отражённому полю |
Методы, унаследованные от класса java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait Поля
ОБЩЕСТВЕННЫЕ
public static final int PUBLIC
Маска из одного бита, представляющая доступ public, который может повлиять на результат lookupModes. Значение 0x01, совпадает со значением бита модификатора public PUBLIC.
- См. также:
- Значения константных полей
ЧАСТНЫЕ
public static final int PRIVATE
Маска из одного бита, представляющая доступ private, который может повлиять на результат lookupModes. Значение 0x02, совпадает со значением бита модификатора private PRIVATE.
- См. также:
- Значения константных полей
ЗАЩИЩЕННЫЕ
public static final int PROTECTED
Маска из одного бита, представляющая доступ protected, который может повлиять на результат lookupModes. Значение 0x04, совпадает со значением бита модификатора protected PROTECTED.
- См. также:
- Значения константных полей
ПАКЕТ
public static final int PACKAGE
Маска из одного бита, представляющая доступ package (доступ по умолчанию), который может повлиять на результат lookupModes. Значение 0x08, которое не имеет осмысленного соответствия ни одному конкретному биту модификатора .
- См. также:
- Значения константных полей
МОДУЛЬ
public static final int MODULE
Маска из одного бита, представляющая доступ module (доступ по умолчанию), который может повлиять на результат lookupModes. Значение 0x10, которое не имеет осмысленного соответствия ни одному конкретному биту модификатора . В сочетании с битом модификатора PUBLIC, Lookup с этим режимом поиска может получить доступ ко всем публичным типам в модуле класса поиска и к публичным типам в пакетах, экспортированных другими модулями в модуль класса поиска.
- С:
- 9
- См. также:
- Значения константных полей
БЕЗУСЛОВНЫЙ
public static final int UNCONDITIONAL
Маска из одного бита, представляющая доступ unconditional, который может повлиять на результат lookupModes. Значение 0x20, которое не имеет осмысленного соответствия ни одному конкретному биту модификатора . Lookup с этим режимом поиска предполагает читаемость. В сочетании с битом модификатора PUBLIC, Lookup с этим режимом поиска может получить доступ ко всем публичным членам публичных типов всех модулей, где тип находится в пакете, который exported unconditionally.
- С:
- 9
- См. также:
-
MethodHandles.publicLookup(), Значения константных полей
Методы
lookupClass
public Class<?> lookupClass()
Указывает, какой класс выполняет поиск. Это тот класс, по отношению к которому выполняются проверки видимости и разрешений доступа.
Класс подразумевает максимальный уровень разрешений доступа, но разрешения могут быть дополнительно ограничены битовой маской lookupModes, которая управляет тем, можно ли получить доступ к непубличным членам.
- Возвращает:
- класс поиска, от имени которого этот объект поиска находит члены
lookupModes
public int lookupModes()
Указывает, какие классы защиты доступа к членам может генерировать этот объект поиска. Результатом является битовая маска битов PUBLIC (0x01), PRIVATE (0x02), PROTECTED (0x04), PACKAGE (0x08), MODULE (0x10) и UNCONDITIONAL (0x20).
У объекта поиска, созданного на классе вызывающего, установлены все возможные биты, за исключением UNCONDITIONAL. Объект поиска на новом классе поиска созданном из предыдущего объекта поиска может иметь некоторые биты режима установленные в ноль. Биты режима также могут быть непосредственно сброшены. После сброса биты режима не могут быть восстановлены из пониженного объекта поиска. Цель этого — ограничить доступ через новый объект поиска, так что он может получить доступ только к именам, к которым можно получить доступ с помощью исходного объекта поиска, а также нового класса поиска.
- Возвращает:
- режимы поиска, которые ограничивают типы доступа, выполняемые этим объектом поиска
- См. также:
-
in(java.lang.Class<?>),dropLookupMode(int)
in
public MethodHandles.Lookup in(Class<?> requestedLookupClass)
Создаёт поиск в указанном новом классе поиска. Результирующий объект будет сообщать о указанном классе как об собственном lookupClass.
Однако, результат Lookup объекта гарантированно не будет иметь больше возможностей доступа, чем исходный. В частности, возможности доступа могут быть потеряны следующим образом:
- Если старый класс поиска находится в
namedмодуле, а новый класс поиска находится в другом модулеM, тогда ни один член, даже публичные члены в экспортированных пакетахM, не будут доступны. Исключением из этого правила является тот случай, когда этот поискpublicLookup, в этом случаеPUBLICдоступ не теряется. - Если старый класс поиска находится в безымянном модуле, а новый класс поиска — в другом модуле, тогда
MODULEдоступ теряется. - Если новый класс поиска отличается от старого, тогда
UNCONDITIONALтеряется. - Если новый класс поиска находится в другом пакете, чем старый, защищённые и стандартные (пакетные) члены не будут доступны.
- Если новый класс поиска не находится в том же пакете, что и старый, частные члены не будут доступны, и защищённые члены не будут доступны в силу наследования. (Защищённые члены могут по-прежнему быть доступны из-за совместного использования пакетов.)
- Если новый класс поиска недоступен для старого класса поиска, тогда ни один член, даже публичный, не будет доступен. (Во всех остальных случаях публичные члены по-прежнему будут доступны.)
Возможности результирующего поиска по загрузке классов (используемые во время вызовов findClass(java.lang.String)) определяются загрузчиком класса поиска, который может измениться из-за этой операции.
- Параметры:
-
requestedLookupClass- желаемый класс поиска для нового объекта поиска - Возвращает:
- объект поиска, который указывает желаемый класс поиска, или тот же объект, если изменений нет
- Исключения:
-
NullPointerException- если аргумент равен null
dropLookupMode
public MethodHandles.Lookup dropLookupMode(int modeToDrop)
Создаёт поиск в том же классе поиска, что и этот объект поиска, но с режимом поиска, который потерял заданный режим поиска. Режим поиска для сброса является одним из PUBLIC, MODULE, PACKAGE, PROTECTED или PRIVATE. PROTECTED и UNCONDITIONAL всегда сбрасываются, поэтому у результирующего режима поиска никогда не будет этих возможностей доступа. При сбросе PACKAGE результирующий поиск не будет иметь PACKAGE или PRIVATE доступа. При сбросе MODULE результирующий поиск не будет иметь MODULE, PACKAGE, или PRIVATE доступа. Если PUBLIC сбрасывается, то результирующий поиск не имеет доступа.
- Параметры:
-
modeToDrop- режим поиска для сброса - Возвращает:
- объект поиска, у которого отсутствует указанный режим, или тот же объект, если изменений нет
- Исключения:
-
IllegalArgumentException- еслиmodeToDropне является одним изPUBLIC,MODULE,PACKAGE,PROTECTED,PRIVATEилиUNCONDITIONAL - C момента:
- 9
- См. также:
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup)
defineClass
public Class<?> defineClass(byte[] bytes)
throws IllegalAccessException Определяет класс для той же загрузчика классов и в том же пакете времени выполнения и домене защиты, что и класс поиска этого поиска.
Режимы поиска для этого поиска должны включать PACKAGE доступ, так как члены по умолчанию (пакета) будут доступны для класса. PACKAGE режим поиска служит для проверки того, что объект поиска был создан вызывающим объектом в пакете времени выполнения (или получен от поиска, изначально созданного кодом с соответствующими привилегиями для целевого класса в пакете времени выполнения).
bytes параметр — это байты класса, являющиеся корректным файлом класса (как определено в Спецификации виртуальной машины Java) с именем класса в том же пакете, что и класс поиска.
Этот метод не выполняет инициализатор класса. Инициализатор класса может быть выполнен в более позднее время, как подробно описано в разделе 12.4 Спецификации языка Java.
Если существует менеджер безопасности, его метод checkPermission сначала вызывается для проверки RuntimePermission("defineClass").
- Параметры:
-
bytes- байты класса - Возвращает:
- объект
Classдля класса - Исключения:
-
IllegalArgumentException- байты предназначены для класса в другом пакете, чем класс поиска -
IllegalAccessException- если у этого поиска нетPACKAGEдоступа -
LinkageError- если класс имеет неправильный формат (ClassFormatError), не может быть проверен (VerifyError), уже определён или происходит другая ошибка привязк -
SecurityException- если доступ запрещён менеджером безопасности -
NullPointerException- еслиbytesявляетсяnull - C момента:
- 9
- См. также:
-
MethodHandles.privateLookupIn(java.lang.Class<?>, java.lang.invoke.MethodHandles.Lookup),dropLookupMode(int),ClassLoader.defineClass(String,byte[],int,int,ProtectionDomain)
toString
public String toString()
Отображает имя класса, из которого будут выполняться поиски. (Имя — то, которое возвращает Class.getName.) Если существуют ограничения на доступ, разрешённый этому поиску, это указывается добавлением суффикса к имени класса, состоящего из косой черты и ключевого слова. Ключевое слово представляет собой наиболее сильный разрешённый доступ, и выбирается следующим образом:
- Если доступ не разрешён, суффикс — "/noaccess".
- Если разрешён только публичный доступ к типам в экспортированных пакетах, суффикс — "/public".
- Если разрешены только публичный доступ и безусловный доступ, суффикс — "/publicLookup".
- Если разрешён только публичный и модульный доступ, суффикс — "/module".
- Если разрешены только публичный, модульный и пакетный доступ, суффикс — "/package".
- Если разрешены только публичный, модульный, пакетный и частный доступ, суффикс — "/private".
MethodHandles.lookup. Объекты, созданные с помощью Lookup.in, всегда имеют ограниченный доступ и отображают суффикс.
(Может показаться странным, что защищённый доступ сильнее, чем частный доступ. Рассматривая его независимо от доступа к пакетам, защищённый доступ теряется первым, поскольку он требует непосредственного наследования между вызывающим и вызываемым объектами.)
- Переопределяет:
-
toStringв классеObject - Возвращает:
- строковое представление объекта.
- См. также:
in(java.lang.Class<?>)
findStatic
public MethodHandle findStatic(Class<?> refc,
String name,
MethodType type)
throws NoSuchMethodException,
IllegalAccessException Генерирует обработчик методов для статического метода. Тип обработчика методов будет таким же, как у метода. (Поскольку статические методы не принимают получателей, дополнительный аргумент получателя не вставляется в тип обработчика методов, как это было бы с findVirtual или findSpecial.) Метод и все его типы аргументов должны быть доступны объекту поиска.
Возвращаемый обработчик методов будет иметь переменную арность тогда и только тогда, когда бит модификатора переменной арности метода (0x0080) установлен.
Если вызывается возвращаемый обработчик методов, класс метода будет инициализирован, если он ещё не был инициализирован.
Пример:
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
"asList", methodType(List.class, Object[].class));
assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
- Параметры:
-
refc- класс, из которого обращается метод -
name- имя метода -
type- тип метода - Возвращает:
- желаемый обработчик метода
- Бросает:
-
NoSuchMethodException- если метод не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если метод неstatic, или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершилась неудачно -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если какой-либо аргумент равен null
findVirtual
public MethodHandle findVirtual(Class<?> refc,
String name,
MethodType type)
throws NoSuchMethodException,
IllegalAccessException Создаёт обработчик метода для виртуального метода. Тип обработчика метода будет таким же, как у метода, с предварительно добавленным типом получателя (обычно refc). Метод и все его типы аргументов должны быть доступны объекту поиска.
При вызове обработчик будет рассматривать первый аргумент как получателя и, для методов, не являющихся приватными, будет выполнять переключение на тип получателя, чтобы определить, какую реализацию метода вызвать. Для приватных методов будет вызываться метод с указанным именем в refc, передавая получателя в качестве объекта. (Действие переключения идентично тому, что выполняется инструкцией invokevirtual или invokeinterface)
Первый аргумент будет типа refc, если класс поиска имеет полный доступ к члену. В противном случае член должен быть protected, и первый аргумент будет ограничен типом класса поиска.
Возвращаемый обработчик метода будет иметь переменную арность, если и только если бит модификатора переменной арности метода (0x0080) установлен.
Из-за общей эквивалентности между инструкциями invokevirtual и обработчиками методов, созданными findVirtual, если класс является MethodHandle, а строка имени равна invokeExact или invoke, полученный обработчик метода эквивалентен обработчику, созданному MethodHandles.exactInvoker или MethodHandles.invoker с тем же аргументом type.
Если класс является VarHandle, а строка имени соответствует имени метода метода с полиморфизмом сигнатур, полученный обработчик метода эквивалентен обработчику, созданному MethodHandles.varHandleInvoker(java.lang.invoke.VarHandle.AccessMode, java.lang.invoke.MethodType) с режимом доступа, соответствующим строке имени, и с теми же аргументами type.
Пример:
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle MH_concat = publicLookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
"hashCode", methodType(int.class));
MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
"hashCode", methodType(int.class));
assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
// interface method:
MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
"subSequence", methodType(CharSequence.class, int.class, int.class));
assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
// constructor "internal method" must be accessed differently:
MethodType MT_newString = methodType(void.class); //()V for new String()
try { assertEquals("impossible", lookup()
.findVirtual(String.class, "<init>", MT_newString));
} catch (NoSuchMethodException ex) { } // OK
MethodHandle MH_newString = publicLookup()
.findConstructor(String.class, MT_newString);
assertEquals("", (String) MH_newString.invokeExact());
- Параметры:
-
refc- класс или интерфейс, из которого обращается метод -
name- имя метода -
type- тип метода, без аргумента получателя - Возвращает:
- желаемый обработчик метода
- Бросает:
-
NoSuchMethodException- если метод не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если метод являетсяstatic, или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершилась неудачно -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если какой-либо аргумент равен null
findConstructor
public MethodHandle findConstructor(Class<?> refc,
MethodType type)
throws NoSuchMethodException,
IllegalAccessException Создаёт обработчик метода, который создаёт объект и инициализирует его, используя конструктор указанного типа. Типы параметров обработчика метода будут такими же, как у конструктора, а тип возвращаемого значения — ссылкой на класс конструктора. Конструктор и все его типы аргументов должны быть доступны объекту поиска.
Запрашиваемый тип должен иметь тип возвращаемого значения void. (Это согласуется с обработкой JVM описателей типов конструкторов.)
Возвращаемый обработчик метода будет иметь переменную арность, если и только если бит модификатора переменной арности конструктора (0x0080) установлен.
Если возвращаемый обработчик метода вызывается, класс конструктора будет инициализирован, если он ещё не был инициализирован.
Пример:
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle MH_newArrayList = publicLookup().findConstructor(
ArrayList.class, methodType(void.class, Collection.class));
Collection orig = Arrays.asList("x", "y");
Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
assert(orig != copy);
assertEquals(orig, copy);
// a variable-arity constructor:
MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
ProcessBuilder.class, methodType(void.class, String[].class));
ProcessBuilder pb = (ProcessBuilder)
MH_newProcessBuilder.invoke("x", "y", "z");
assertEquals("[x, y, z]", pb.command().toString());
- Параметры:
-
refc- класс или интерфейс, из которого обращается метод -
type- тип метода, без аргумента получателя, и типом возврата void - Возвращает:
- желаемый обработчик метода
- Бросает:
-
NoSuchMethodException- если конструктор не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершилась неудачно -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если какой-либо аргумент равен null
findClass
public Class<?> findClass(String targetName)
throws ClassNotFoundException,
IllegalAccessException Ищет класс по имени из контекста поиска, определённого этим объектом Lookup. Статический инициализатор класса не выполняется.
Контекст поиска определяется классом поиска lookup class, его загрузчиком классов и режимами поиска. В частности, метод сначала пытается загрузить запрашиваемый класс, а затем определяет, доступен ли класс для этого объекта поиска.
- Параметры:
-
targetName- полное имя класса, подлежащего поиску. - Возвращает:
- запрашиваемый класс.
- Бросает:
-
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
LinkageError- если произошла ошибка связи -
ClassNotFoundException- если класс не может быть загружен загрузчиком класса поиска. -
IllegalAccessException- если класс недоступен, используя разрешенные режимы доступа. -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе - Since:
- 9
accessClass
public Class<?> accessClass(Class<?> targetClass)
throws IllegalAccessException Определяет, можно ли получить доступ к классу из контекста поиска, определённого этим объектом Lookup. Статический инициализатор класса не выполняется.
Контекст поиска определяется классом поиска lookup class и режимами поиска.
- Параметры:
-
targetClass- класс, для которого проверяется доступ - Возвращает:
- класс, для которого была проверена возможность доступа
- Бросает:
-
IllegalAccessException- если к классу нельзя получить доступ из класса поиска, используя разрешённые режимы доступа. -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе - Since:
- 9
findSpecial
public MethodHandle findSpecial(Class<?> refc,
String name,
MethodType type,
Class<?> specialCaller)
throws NoSuchMethodException,
IllegalAccessException Создаёт ранний обработчик метода для виртуального метода. Он пропустит проверки переопределённых методов у получателя, как если бы он был вызван инструкцией invokespecial из внутри явно указанного specialCaller. Тип обработчика метода будет таким же, как у метода, с надлежащим ограничением типа получателя. (Тип получателя будет specialCaller или подклассом.) Метод и все его типы аргументов должны быть доступны объекту поиска.
Перед разрешением метода, если явно указанный вызывающий класс не идентичен классу поиска, или если у этого объекта поиска нет привилегий частного доступа, доступ отказывается.
Возвращаемый обработчик метода будет иметь переменную арность, если и только если бит модификатора переменной арности метода (0x0080) установлен.
(Примечание: внутренние методы JVM с именем "<init>" не видны для этого API, даже если инструкция invokespecial может ссылаться на них в особых случаях. Используйте findConstructor, чтобы безопасно получить доступ к методам инициализации экземпляров.)
Пример:
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
static class Listie extends ArrayList {
public String toString() { return "[wee Listie]"; }
static Lookup lookup() { return MethodHandles.lookup(); }
}
...
// no access to constructor via invokeSpecial:
MethodHandle MH_newListie = Listie.lookup()
.findConstructor(Listie.class, methodType(void.class));
Listie l = (Listie) MH_newListie.invokeExact();
try { assertEquals("impossible", Listie.lookup().findSpecial(
Listie.class, "<init>", methodType(void.class), Listie.class));
} catch (NoSuchMethodException ex) { } // OK
// access to super and self methods via invokeSpecial:
MethodHandle MH_super = Listie.lookup().findSpecial(
ArrayList.class, "toString" , methodType(String.class), Listie.class);
MethodHandle MH_this = Listie.lookup().findSpecial(
Listie.class, "toString" , methodType(String.class), Listie.class);
MethodHandle MH_duper = Listie.lookup().findSpecial(
Object.class, "toString" , methodType(String.class), Listie.class);
assertEquals("[]", (String) MH_super.invokeExact(l));
assertEquals(""+l, (String) MH_this.invokeExact(l));
assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
try { assertEquals("inaccessible", Listie.lookup().findSpecial(
String.class, "toString", methodType(String.class), Listie.class));
} catch (IllegalAccessException ex) { } // OK
Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
- Параметры:
-
refc- класс или интерфейс, из которого обращается метод -
name- имя метода (которое не должно быть "<init>") -
type- тип метода, без аргумента получателя -
specialCaller- предлагаемый вызывающий класс для выполненияinvokespecial - Возвращает:
- желаемый обработчик метода
- Бросает:
-
NoSuchMethodException- если метод не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если метод являетсяstatic, или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершилась неудачно -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если какой-либо аргумент равен null
findGetter
public MethodHandle findGetter(Class<?> refc,
String name,
Class<?> type)
throws NoSuchFieldException,
IllegalAccessException Создаёт обработчик метода, обеспечивающий чтение значения нестатического поля. Тип обработчика метода будет иметь тип значения поля в качестве типа возвращаемого значения. Единственный аргумент обработчика метода будет экземпляром, содержащим поле. Проверка доступа выполняется немедленно от имени класса поиска.
- Параметры:
-
refc- класс или интерфейс, из которого обращается метод -
name- имя поля -
type- тип поля - Возвращает:
- обработчик метода, который может загружать значения из поля
- Бросает:
-
NoSuchFieldException- если поле не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если поле являетсяstatic -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если какой-либо аргумент равен null - См. также:
findVarHandle(Class, String, Class)
findSetter
public MethodHandle findSetter(Class<?> refc,
String name,
Class<?> type)
throws NoSuchFieldException,
IllegalAccessException Создаёт обработчик метода, предоставляющий доступ для записи в нестатическое поле. Тип обработчика метода будет иметь возвращаемый тип void. Обработчик метода будет принимать два аргумента: экземпляр, содержащий поле, и значение, которое нужно сохранить. Второй аргумент будет иметь тип значения поля.
- Параметры:
-
refc- класс или интерфейс, из которого происходит доступ к методу -
name- имя поля -
type- тип поля - Возвращаемое значение:
- обработчик метода, который может сохранять значения в поле
- Исключения:
-
NoSuchFieldException- если поле не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если полеstatic -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если любой аргумент имеет значение null - См. также:
findVarHandle(Class, String, Class)
findVarHandle
public VarHandle findVarHandle(Class<?> recv,
String name,
Class<?> type)
throws NoSuchFieldException,
IllegalAccessException Создаёт VarHandle, предоставляющий доступ к нестатическому полю name типа type, объявленному в классе типа recv. Тип переменной VarHandle - type, а тип координаты - recv.
Проверка доступа выполняется немедленно от имени класса поиска.
Некоторые режимы доступа возвращаемого VarHandle не поддерживаются в следующих условиях:
- если поле объявлено
final, то режимы записи, атомарного обновления, атомарного числового обновления и атомарного побитового обновления не поддерживаются. - если тип поля отличается от
byte,short,char,int,long,float, илиdouble, то режимы атомарного числового обновления не поддерживаются. - если тип поля отличается от
boolean,byte,short,char,intилиlong, то режимы атомарного побитового обновления не поддерживаются.
Если поле объявлено volatile, то возвращаемый VarHandle переопределит доступ к полю (фактически проигнорирует объявление volatile) в соответствии с его указанными режимами доступа.
Если тип поля - float или double, то режимы числового и атомарного обновления сравнивают значения, используя их битовую представление (см. Float.floatToRawIntBits(float) и Double.doubleToRawLongBits(double) соответственно).
- Примечание API:
- Побитовое сравнение значений
floatилиdouble, выполняемое режимами числового и атомарного обновления, отличается от оператора==и методовFloat.equals(java.lang.Object)иDouble.equals(java.lang.Object), в частности, относительно сравнения значений NaN или сравнения-0.0с+0.0. Следует проявлять осторожность при выполнении операции сравнения и установки или сравнения и обмена с такими значениями, поскольку операция может неожиданно завершиться неудачей. Существует множество возможных значений NaN, которые считаютсяNaNв Java, хотя ни одна операция с плавающей точкой IEEE 754, предоставляемая Java, не может их различать. Неудача операции может произойти, если ожидаемое или наблюдаемое значение является значением NaN и оно преобразуется (возможно, в платформенно-специфическом порядке) в другое значение NaN, и, следовательно, имеет другое битовое представление (см.Float.intBitsToFloat(int)илиDouble.longBitsToDouble(long)для получения более подробной информации). Значения-0.0и+0.0имеют разные битовые представления, но считаются равными при использовании оператора==. Неудача операции может произойти, если, например, числовой алгоритм вычисляет ожидаемое значение, скажем,-0.0, и ранее вычислил наблюдаемое значение, скажем,+0.0. - Параметры:
-
recv- класс-получатель, типаR, который объявляет нестатическое поле -
name- имя поля -
type- тип поля, типаT - Возвращаемое значение:
- VarHandle, предоставляющий доступ к нестатическим полям.
- Исключения:
-
NoSuchFieldException- если поле не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если полеstatic -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если любой аргумент имеет значение null - С:
- 9
findStaticGetter
public MethodHandle findStaticGetter(Class<?> refc,
String name,
Class<?> type)
throws NoSuchFieldException,
IllegalAccessException Создаёт обработчик метода, предоставляющий доступ для чтения к статическому полю. Тип обработчика метода будет иметь возвращаемый тип типа значения поля. Обработчик метода не будет принимать аргументов. Проверка доступа выполняется немедленно от имени класса поиска.
Если вызывается возвращаемый обработчик метода, класс поля будет инициализирован, если он ещё не был инициализирован.
- Параметры:
-
refc- класс или интерфейс, из которого происходит доступ к методу -
name- имя поля -
type- тип поля - Возвращаемое значение:
- обработчик метода, который может загружать значения из поля
- Исключения:
-
NoSuchFieldException- если поле не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если поле неstatic -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если любой аргумент имеет значение null
findStaticSetter
public MethodHandle findStaticSetter(Class<?> refc,
String name,
Class<?> type)
throws NoSuchFieldException,
IllegalAccessException Создаёт обработчик метода, предоставляющий доступ для записи в статическое поле. Тип обработчика метода будет иметь возвращаемый тип void. Обработчик метода будет принимать один аргумент, типа типа значения поля, значение, которое нужно сохранить. Проверка доступа выполняется немедленно от имени класса поиска.
Если вызывается возвращаемый обработчик метода, класс поля будет инициализирован, если он ещё не был инициализирован.
- Параметры:
-
refc- класс или интерфейс, из которого происходит доступ к методу -
name- имя поля -
type- тип поля - Возвращаемое значение:
- обработчик метода, который может сохранять значения в поле
- Исключения:
-
NoSuchFieldException- если поле не существует -
IllegalAccessException- если проверка доступа завершилась неудачно, или если поле неstatic -
SecurityException- если менеджер безопасности присутствует и он отказал в доступе -
NullPointerException- если любой аргумент имеет значение null
findStaticVarHandle
public VarHandle findStaticVarHandle(Class<?> decl,
String name,
Class<?> type)
throws NoSuchFieldException,
IllegalAccessException Создаёт VarHandle, предоставляющий доступ к статическому полю name типа type , объявленному в классе типа decl. Тип переменной VarHandle - type, а тип координаты отсутствует.
Проверка доступа выполняется немедленно от имени класса поиска.
Если на возвращаемый VarHandle производится операция, класс объявления будет инициализирован, если он ещё не был инициализирован.
Некоторые режимы доступа возвращаемого VarHandle не поддерживаются в следующих условиях:
- если поле объявлено
final, то режимы записи, атомарного обновления, атомарного числового обновления и атомарного побитового обновления не поддерживаются. - если тип поля отличается от
byte,short,char,int,long,float, илиdouble, то режимы атомарного числового обновления не поддерживаются. - если тип поля отличается от
boolean,byte,short,char,intилиlong, то режимы атомарного побитового обновления не поддерживаются.
Если поле объявлено volatile, то возвращаемый VarHandle переопределит доступ к полю (фактически проигнорирует объявление volatile) в соответствии с его указанными режимами доступа.
Если тип поля - float или double, то режимы числового и атомарного обновления сравнивают значения, используя их битовую представление (см. Float.floatToRawIntBits(float) и Double.doubleToRawLongBits(double) соответственно).
- Примечание API:
- Побитовое сравнение значений
floatили значенийdouble, выполняемое режимами доступа к числовым и атомным обновлениям, отличается от примитивного оператора==и методовFloat.equals(java.lang.Object)иDouble.equals(java.lang.Object), особенно при сравнении значений NaN или сравнении-0.0с+0.0. Следует проявлять осторожность при выполнении операции compare and set или compare and exchange с такими значениями, так как операция может неожиданно завершиться неудачей. Существует множество возможных значений NaN, которые считаютсяNaNв Java, хотя ни одна операция с плавающей точкой IEEE 754, предоставляемая Java, не может отличить их друг от друга. Ошибка операции может возникнуть, если ожидаемое или наблюдаемое значение является значением NaN, и оно преобразуется (возможно, платформоспецифическим способом) в другое значение NaN, и, следовательно, имеет другое побитовое представление (см.Float.intBitsToFloat(int)илиDouble.longBitsToDouble(long)для получения более подробной информации). Значения-0.0и+0.0имеют разные побитовые представления, но считаются равными при использовании примитивного оператора==. Ошибка операции может возникнуть, если, например, числовой алгоритм вычисляет ожидаемое значение, скажем,-0.0, а ранее вычисляет наблюдаемое значение, скажем,+0.0. - Параметры:
-
decl- класс, объявляющий статическое поле -
name- имя поля -
type- тип поля, типаT - Возвращает:
- VarHandle, предоставляющий доступ к статическому полю
- Исключения:
-
NoSuchFieldException- если поле не существует -
IllegalAccessException- если проверка доступа завершилась неудачей или если поле неstatic -
SecurityException- если менеджер безопасности присутствует и он отклоняет доступ -
NullPointerException- если какой-либо аргумент равен null - С:
- 9
bind
public MethodHandle bind(Object receiver,
String name,
MethodType type)
throws NoSuchMethodException,
IllegalAccessException Создает метод-обработчик с ранним связыванием для нестатического метода. Получатель должен иметь супертип defc, в котором метод с заданным именем и типом доступен для класса поиска. Метод и все его типы аргументов должны быть доступны для объекта поиска. Тип метода-обработчика будет таким же, как у метода, без вставки дополнительного параметра получателя. Заданный получатель будет привязан к методу-обработчику, поэтому каждый вызов метода-обработчика будет вызывать запрашиваемый метод на заданном получателе.
Возвращаемый метод-обработчик будет иметь переменную арность, если и только если бит модификатора переменной арности метода (0x0080) установлен и аргумент массива с последующим аргументом не является единственным аргументом. (Если аргумент массива с последующим аргументом является единственным аргументом, заданное значение получателя будет привязано к нему.)
Это почти эквивалентно следующему коду, с некоторыми различиями, отмеченными ниже:
import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; ... MethodHandle mh0 = lookup().findVirtual(defc, name, type); MethodHandle mh1 = mh0.bindTo(receiver); mh1 = mh1.withVarargs(mh0.isVarargsCollector()); return mh1;где
defc — это либо receiver.getClass(), либо супертип этого класса, в котором запрашиваемый метод доступен для класса поиска. (В отличие от bind, bindTo не сохраняет переменную арность. Кроме того, bindTo может выбросить ClassCastException в случаях, когда bind выбросил бы IllegalAccessException, как в случае, когда член является protected, а получатель ограничен findVirtual классом поиска.)- Параметры:
-
receiver- объект, из которого осуществляется доступ к методу -
name- имя метода -
type- тип метода, без аргумента получателя - Возвращает:
- требуемый метод-обработчик
- Исключения:
-
NoSuchMethodException- если метод не существует -
IllegalAccessException- если проверка доступа завершилась неудачей или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершился неудачей -
SecurityException- если менеджер безопасности присутствует и он отклоняет доступ -
NullPointerException- если какой-либо аргумент равен null - См. также:
-
MethodHandle.bindTo(java.lang.Object),findVirtual(java.lang.Class<?>, java.lang.String, java.lang.invoke.MethodType)
unreflect
public MethodHandle unreflect(Method m)
throws IllegalAccessException Создает прямой метод-обработчик для m, если у класса поиска есть разрешение. Если m не статический, аргумент получателя обрабатывается как начальный аргумент. Если m виртуальный, переопределение учитывается при каждом вызове. В отличие от API ядра отражения, исключения не обертываются. Тип метода-обработчика будет таким же, как у метода, с типом получателя впереди (но только если он не статический). Если флаг accessible метода не установлен, проверка доступа выполняется немедленно от имени класса поиска. Если m не является общедоступным, не следует делиться полученным обработчиком с недоверенными сторонами.
Возвращаемый метод-обработчик будет иметь переменную арность, если и только если бит модификатора переменной арности метода (0x0080) установлен.
Если m статический, и если вызывается возвращаемый метод-обработчик, класс метода инициализируется, если он еще не был инициализирован.
- Параметры:
-
m- отраженный метод - Возвращает:
- метод-обработчик, который может вызвать отраженный метод
- Исключения:
-
IllegalAccessException- если проверка доступа завершилась неудачей или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершился неудачей -
NullPointerException- если аргумент равен null
unreflectSpecial
public MethodHandle unreflectSpecial(Method m,
Class<?> specialCaller)
throws IllegalAccessException Создает метод-обработчик для отраженного метода. Он пропустит проверки переопределенных методов получателя, как если бы он был вызван из инструкции invokespecial изнутри явно указанного specialCaller. Тип метода-обработчика будет таким же, как у метода, с надлежащим образом ограниченным типом получателя впереди. (Тип получателя будет specialCaller или подтипом). Если флаг accessible метода не установлен, проверка доступа выполняется немедленно от имени класса поиска, как будто инструкция invokespecial была связана.
Перед разрешением метода, если явно указанный класс вызывающего не идентичен классу поиска или если у этого объекта поиска нет привилегий частного доступа, доступ завершается неудачей.
Возвращаемый метод-обработчик будет иметь переменную арность, если и только если бит модификатора переменной арности метода (0x0080) установлен.
- Параметры:
-
m- отраженный метод -
specialCaller- класс, номинально вызывающий метод - Возвращает:
- метод-обработчик, который может вызвать отраженный метод
- Исключения:
-
IllegalAccessException- если проверка доступа завершилась неудачей или если метод являетсяstatic, или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершился неудачей -
NullPointerException- если какой-либо аргумент равен null
unreflectConstructor
public MethodHandle unreflectConstructor(Constructor<?> c)
throws IllegalAccessException Создает метод-обработчик для отраженного конструктора. Тип метода-обработчика будет таким же, как у конструктора, с типом возврата, измененным на класс объявления. Метод-обработчик выполнит операцию newInstance, создав новый экземпляр класса конструктора по аргументам, переданным методу-обработчику.
Если флаг accessible конструктора не установлен, проверка доступа выполняется немедленно от имени класса поиска.
Возвращаемый метод-обработчик будет иметь переменную арность, если и только если бит модификатора переменной арности конструктора (0x0080) установлен.
Если вызывается возвращаемый метод-обработчик, класс конструктора инициализируется, если он еще не был инициализирован.
- Параметры:
-
c- отраженный конструктор - Возвращает:
- метод-обработчик, который может вызвать отраженный конструктор
- Исключения:
-
IllegalAccessException- если проверка доступа завершилась неудачей или если бит модификатора переменной арности метода установлен, иasVarargsCollectorзавершился неудачей -
NullPointerException- если аргумент равен null
unreflectGetter
public MethodHandle unreflectGetter(Field f)
throws IllegalAccessException Создает метод-обработчик, предоставляющий доступ для чтения к отраженному полю. Тип метода-обработчика будет иметь тип значения поля в качестве типа возврата. Если поле статическое, метод-обработчик не будет принимать аргументы. В противном случае его единственный аргумент будет экземпляром, содержащим поле. Если флаг accessible поля не установлен, проверка доступа выполняется немедленно от имени класса поиска.
Если поле статическое, и если вызывается возвращаемый метод-обработчик, класс поля инициализируется, если он еще не был инициализирован.
- Параметры:
-
f- отраженное поле - Возвращает:
- метод-обработчик, который может загружать значения из отраженного поля
- Исключения:
-
IllegalAccessException- если проверка доступа завершилась неудачей -
NullPointerException- если аргумент равен null
unreflectSetter
public MethodHandle unreflectSetter(Field f)
throws IllegalAccessException Создает метод-обработчик, предоставляющий доступ для записи к отраженному полю. Тип метода-обработчика будет иметь тип void в качестве типа возврата. Если поле статическое, метод-обработчик будет принимать один аргумент типа значения поля — значение, которое нужно сохранить. В противном случае двумя аргументами будут экземпляр, содержащий поле, и значение, которое нужно сохранить. Если флаг accessible поля не установлен, проверка доступа выполняется немедленно от имени класса поиска.
Если поле статическое, и если вызывается возвращаемый метод-обработчик, класс поля инициализируется, если он еще не был инициализирован.
- Параметры:
-
f- отражённое поле - Возвращает:
- дескриптор метода, который может хранить значения в отражённом поле
- Выбрасывает:
-
IllegalAccessException- если проверка доступа завершилась неудачно -
NullPointerException- если аргумент равен null
unreflectVarHandle
public VarHandle unreflectVarHandle(Field f)
throws IllegalAccessException Создаёт VarHandle, обеспечивающий доступ к отражённому полю f типа T, объявленному в классе типа R. Тип переменной VarHandle — T. Если поле не статическое, у VarHandle есть один тип координаты — R. В противном случае поле статическое, и у VarHandle нет типов координат.
Проверка доступа выполняется немедленно от имени класса поиска, независимо от значения флага accessible поля.
Если поле статическое, и если с возвращённым VarHandle производится работа, класс, объявляющий поле, будет инициализирован, если он ещё не был инициализирован.
Некоторые режимы доступа возвращённого VarHandle не поддерживаются в следующих условиях:
- если поле объявлено
final, то режимы записи, атомарного обновления, атомарного числового обновления и атомарного побитового обновления не поддерживаются. - если тип поля — любой другой, кроме
byte,short,char,int,long,float, илиdouble, то режимы атомарного числового обновления не поддерживаются. - если тип поля — любой другой, кроме
boolean,byte,short,char,intилиlong, то режимы атомарного побитового обновления не поддерживаются.
Если поле объявлено volatile, то возвращённый VarHandle переопределит доступ к полю (фактически проигнорирует объявление volatile) в соответствии со своими заданными режимами доступа.
Если тип поля — float или double, то режимы числового и атомарного обновления сравнивают значения с использованием их двоичного представления (см. Float.floatToRawIntBits(float) и Double.doubleToRawLongBits(double) соответственно).
- Примечание API:
- Побитовое сравнение значений
floatили значенийdouble, как выполняется режимами числового и атомарного обновления, отличается от оператора==и методовFloat.equals(java.lang.Object)иDouble.equals(java.lang.Object), в частности, относительно сравнения значений NaN или сравнения-0.0с+0.0. Следует проявлять осторожность при выполнении операции сравнения и установки или сравнения и обмена со значениями такого рода, поскольку операция может неожиданно завершиться неудачей. В Java существует множество возможных значений NaN, которые считаютсяNaNв Java, хотя ни одна операция с плавающей точкой IEEE 754, предоставляемая Java, не может отличить их друг от друга. Неудача операции может произойти, если ожидаемое или свидетельское значение является значением NaN и оно преобразуется (возможно, платформенно-специфическим способом) в другое значение NaN и, таким образом, имеет другое двоичное представление (см.Float.intBitsToFloat(int)илиDouble.longBitsToDouble(long)для получения дополнительной информации). Значения-0.0и+0.0имеют разные двоичные представления, но считаются равными при использовании оператора==. Неудача операции может произойти, например, если числовой алгоритм вычисляет ожидаемое значение, скажем,-0.0, и ранее вычислил свидетельское значение, скажем,+0.0. - Параметры:
-
f- отражённое поле с типом поляTи классом, объявляющим поле, типаR - Возвращает:
- VarHandle, обеспечивающий доступ к нестатическим полям или статическому полю
- Выбрасывает:
-
IllegalAccessException- если проверка доступа завершилась неудачно -
NullPointerException- если аргумент равен null - С:
- 9
revealDirect
public MethodHandleInfo revealDirect(MethodHandle target)
Раскрывает прямой дескриптор метода, созданный этим объектом поиска или подобным ему. Проверки безопасности и доступа выполняются для обеспечения того, что этот объект поиска может воспроизвести целевой дескриптор метода. Это означает, что раскрытие может завершиться неудачей, если целевой объект является прямым дескриптором метода, но был создан несвязанным объектом поиска. Это может произойти, если дескриптор метода является зависимым от вызывающего и был создан объектом поиска для другого класса.
- Параметры:
-
target- прямой дескриптор метода для раскрытия в компоненты символической ссылки - Возвращает:
- символическая ссылка, которая может быть использована для реконструкции этого дескриптора метода из этого объекта поиска
- Выбрасывает:
-
SecurityException- если диспетчер безопасности присутствует и он отказывается предоставить доступ -
IllegalArgumentException- если целевой объект не является прямым дескриптором метода или если проверка доступа завершилась неудачно -
NullPointerException- если целевой объектnull - С:
- 1.8
- См. также:
MethodHandleInfo
hasPrivateAccess
public boolean hasPrivateAccess()
Возвращает true, если у этого объекта поиска есть доступ PRIVATE.
- Возвращает:
-
trueесли у этого объекта поиска есть доступPRIVATE. - С:
- 9
© 1993, 2020, 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.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html