Spec-Zone.ru › OpenJDK 17

Интерфейс ResourceScope

Все суперинтерфейсы:
AutoCloseable
public sealed interface ResourceScope extends AutoCloseable
Область ресурсов управляет жизненным циклом одного или нескольких ресурсов. Ресурсы (например, MemorySegment) связанные с областью ресурсов, могут быть доступны только пока область ресурсов активна (см. isAlive()), и только потоком, ассоциированным с областью ресурсов (если таковой имеется).

Явные области ресурсов

Области ресурсов, полученные из newConfinedScope(), newSharedScope() поддерживают детерминированное освобождение; мы называем эти области ресурсов явными областями. Явные области ресурсов могут быть закрыты явно (см. close()). Когда область ресурсов закрывается, она больше не активна (см. isAlive()), и последующие операции с ресурсами, связанными с этой областью (например, попытка доступа к экземпляру MemorySegment) завершатся ошибкой IllegalStateException.

Закрытие области ресурсов вызовет все действия по очистке, связанные с этой областью (см. addCloseAction(Runnable)), и, возможно, освободит связанные с ней ресурсы (например):

  • закрытие области, связанной с сегментом системной памяти, приводит к освобождению связанной с ним системной памяти (см. MemorySegment.allocateNative(long, ResourceScope), или SegmentAllocator.arenaAllocator(ResourceScope))
  • закрытие области, связанной с отображённым сегментом памяти, приводит к отображению файла, с которым связан сегмент, (см. MemorySegment.mapFile(Path, long, long, FileChannel.MapMode, ResourceScope))
  • закрытие области, связанной со «stub» вызова, приводит к освобождению «stub» (см. CLinker.upcallStub(MethodHandle, FunctionDescriptor, ResourceScope)

Иногда явные области могут быть связаны с экземпляром Cleaner (см. newConfinedScope(Cleaner) и newSharedScope(Cleaner)). Такие области ресурсов называются управляемыми. Управляемая область ресурсов закрывается автоматически, когда экземпляр области становится недоступным.

Управляемые области могут быть полезны для прогнозируемого и детерминированного освобождения ресурсов, предотвращая при этом случайные утечки системной памяти. Если управляемая область ресурсов закрывается явно, дальнейших действий при потере доступности области не происходит. То есть, действия по очистке (см. addCloseAction(Runnable)), связанные с областью ресурсов (управляемой или нет), вызываются ровно один раз.

Неявные области ресурсов

Области ресурсов, полученные из newImplicitScope(), не могут быть закрыты явно. Такие области ресурсов называются неявными. Вызов close() для неявной области ресурсов всегда приведёт к исключению. Ресурсы, связанные с неявными областями, освобождаются, когда область становится недоступной.

Важной неявной областью является так называемая глобальная область; глобальная область — это неявная область, которая гарантированно никогда не станет недоступной. В результате глобальная область никогда не попытается освободить ресурсы, с ней связанные. Такие ресурсы должны, при необходимости, управляться клиентами независимо.

Привязка к потоку

Области ресурсов могут быть разделены на две категории: области ресурсов, привязанные к потоку, и общие области ресурсов.

Области ресурсов, привязанные к потоку (см. newConfinedScope()), поддерживают жёсткую привязку к потоку. При создании им назначается владеющий поток, обычно поток, который инициировал операцию создания (см. ownerThread()). После создания привязанной к потоку области ресурсов, только владеющий поток сможет напрямую управлять ресурсами, связанными с этой областью. Любая попытка доступа к ресурсам из потока, отличного от владеющего, приведёт к сбою во время выполнения.

Общие области ресурсов (см. newSharedScope() и newImplicitScope()), с другой стороны, не имеют владеющего потока; ресурсы, связанные с такими общими областями, могут быть доступны нескольким потокам. Это может быть полезно, когда несколько потоков нуждаются в одновременном доступе к одному ресурсу (например, в случае параллельной обработки). Например, клиент может получить Spliterator из общего сегмента, который затем может быть использован для разделения сегмента и разрешения нескольким потокам работать параллельно над отдельными фрагментами сегмента. Следующий код может быть использован для суммирования всех целочисленных значений в сегменте памяти параллельно:


SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, MemoryLayouts.JAVA_INT);
try (ResourceScope scope = ResourceScope.newSharedScope()) {
    MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
    VarHandle VH_int = SEQUENCE_LAYOUT.elementLayout().varHandle(int.class);
    int sum = StreamSupport.stream(segment.spliterator(SEQUENCE_LAYOUT), true)
        .mapToInt(s -> (int)VH_int.get(s.address()))
        .sum();
}
 

Явные общие области ресурсов, хотя и мощные, должны использоваться с осторожностью: если один или несколько потоков обращаются к ресурсу, связанному с общей областью, в то время как другая область закрывается другим потоком, может возникнуть ошибка в обоих потоках. Клиенты должны избегать многократного закрытия общей области ресурсов (например, многократного вызова close() до тех пор, пока не будет выброшено исключение). Вместо этого, клиенты общих областей ресурсов всегда должны обеспечивать правильные механизмы синхронизации (например, используя обработчики области ресурсов, см. ниже), чтобы потоки, закрывающие общие области ресурсов, никогда не конфликтовали с потоками, получающими доступ к ресурсам, управляемым теми же областями.

Обработчики областей ресурсов

Области ресурсов могут быть сделаны незакрываемыми путём получения одного или нескольких обработчиков области ресурсов (см. acquire()). Обработчик области ресурсов может быть использован, чтобы убедиться, что ресурсы, связанные с данной областью ресурсов (явной или неявной), не будут освобождены в течение определённого периода времени — например, во время критической области кода, затрагивающей один или несколько ресурсов, связанных с областью. Например, явная область ресурсов может быть закрыта только после закрытия всех обработчиков, полученных для данной области (см. close()). Это может быть полезно, когда клиентам нужно выполнить критическую операцию с сегментом памяти, в течение которой они должны убедиться, что сегмент не будет освобождён; это можно сделать следующим образом:

MemorySegment segment = ...
ResourceScope.Handle segmentHandle = segment.scope().acquire()
try {
   <critical operation on segment>
} finally {
   segment.scope().release(segmentHandle);
}
 
Получение неявных областей ресурсов также возможно, но зачастую не требуется: так как ресурсы, связанные с неявной областью, будут освобождены только тогда, когда область станет недоступной, клиенты могут использовать, например, Reference.reachabilityFence(Object), чтобы убедиться, что ресурсы, связанные с неявными областями, не будут освобождены преждевременно. При этом приведённый выше фрагмент кода работает (тривиально) и для неявных областей.
Требования к реализации:
Реализации этого интерфейса являются неизменяемыми, потокобезопасными и базовыми.

Краткое описание вложенных классов

Модификатор и тип Интерфейс Описание
static interface  ResourceScope.Handle
Абстракция, моделирующая дескриптор области ресурсов.

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

Модификатор и тип Метод Описание
ResourceScope.Handle acquire()
Получает дескриптор области ресурсов, связанный с этой областью ресурсов.
void addCloseAction(Runnable runnable)
Добавляет пользовательское действие очистки, которое будет выполнено при закрытии области ресурсов.
void close()
Закрывает эту область ресурсов.
static ResourceScope globalScope()
Возвращает неявную область, которая предполагается всегда активной.
boolean isAlive()
Активна ли эта область ресурсов?
boolean isImplicit()
Является ли эта область ресурсов неявной областью?
static ResourceScope newConfinedScope()
Создает новую ограниченную область.
static ResourceScope newConfinedScope(Cleaner cleaner)
Создает новую ограниченную область, управляемую Cleaner.
static ResourceScope newImplicitScope()
Создает новую неявную область.
static ResourceScope newSharedScope()
Создает новую общую область.
static ResourceScope newSharedScope(Cleaner cleaner)
Создает новую общую область, управляемую Cleaner.
Thread ownerThread()
Поток, владеющий этой областью ресурсов.
void release(ResourceScope.Handle handle)
Освобождает предоставленный дескриптор области ресурсов.

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

isAlive

boolean isAlive()
Активна ли эта область ресурсов?
Возвращает:
true, если эта область ресурсов активна.
См. также:
  • close()

ownerThread

Thread ownerThread()
Поток, владеющий этой областью ресурсов.
Возвращает:
владеющий этой областью ресурсов поток или null если эта область ресурсов общая.

isImplicit

boolean isImplicit()
Является ли эта область ресурсов неявной областью?
Возвращает:
true, если эта область является неявной областью.
См. также:
  • newImplicitScope()
  • globalScope()

close

void close()
Закрывает эту область ресурсов. В качестве побочного эффекта, если эта операция завершится без исключений, эта область будет помечена как неактивная, и последующие операции с ресурсами, связанными с этой областью, завершатся ошибкой IllegalStateException. Кроме того, при успешном закрытии все нативные ресурсы, связанные с этой областью ресурсов, будут освобождены.
Определено в:
close в интерфейсе AutoCloseable
Примечание API:
Эта операция не является идемпотентной; т.е., закрытие уже закрытой области ресурсов всегда приводит к возбуждению исключения. Это отражает сознательное конструкторское решение: переходы состояния области ресурсов должны быть явными в коде клиента; ошибка в любом из этих переходов показывает ошибку в логике приложения.
Исключение:
IllegalStateException - если выполняется одно из следующих условий:
  • эта область ресурсов не активна
  • эта область ресурсов ограниченная, и этот метод вызывается из потока, отличного от потока, владеющего этой областью ресурсов
  • эта область ресурсов общая и к ресурсу, связанному с этой областью, обращаются во время вызова этого метода
  • один или несколько дескрипторов (см. acquire()) связанные с этой областью ресурсов, не были освобождены
UnsupportedOperationException - если эта область ресурсов неявная.

addCloseAction

void addCloseAction(Runnable runnable)
Добавляет пользовательское действие очистки, которое будет выполнено при закрытии области ресурсов. Порядок вызова пользовательских действий очистки после закрытия области не определен.
Параметры:
runnable - пользовательское действие очистки, которое будет связано с этой областью.
Исключение:
IllegalStateException - если эта область уже закрыта.

acquire

ResourceScope.Handle acquire()
Получает дескриптор области ресурсов, связанный с этой областью ресурсов. Явную область ресурсов нельзя закрыть, пока все дескрипторы области ресурсов, полученные из нее, не будут освобождены.
Возвращает:
дескриптор области ресурсов.

release

void release(ResourceScope.Handle handle)
Освобождает предоставленный дескриптор области ресурсов. Этот метод идемпотентен, т.е. многократное освобождение одного и того же дескриптора не имеет эффекта.
Параметры:
handle - дескриптор области ресурсов, который необходимо освободить.
Исключение:
IllegalArgumentException - если предоставленный дескриптор не связан с этой областью.

newConfinedScope

static ResourceScope newConfinedScope()
Создает новую ограниченную область. Результирующая область закрываемая и не управляется Cleaner.
Возвращает:
новую ограниченную область.

newConfinedScope

static ResourceScope newConfinedScope(Cleaner cleaner)
Создает новую ограниченную область, управляемую Cleaner.
Параметры:
cleaner - очиститель, который должен быть связан с возвращаемой областью.
Возвращает:
новую ограниченную область, управляемую cleaner.
Исключение:
NullPointerException - если cleaner == null.

newSharedScope

static ResourceScope newSharedScope()
Создает новую общую область. Результирующая область закрываемая и не управляется Cleaner.
Возвращает:
новую общую область.

newSharedScope

static ResourceScope newSharedScope(Cleaner cleaner)
Создает новую общую область, управляемую Cleaner.
Параметры:
cleaner - очиститель, который должен быть связан с возвращаемой областью.
Возвращает:
новую общую область, управляемую cleaner.
Исключение:
NullPointerException - если cleaner == null.

newImplicitScope

static ResourceScope newImplicitScope()
Создает новую неявную область. Неявная область — это управляемая, общая и незакрываемая область, которая имеет только неявное закрытие. Поскольку неявные области могут быть закрыты только неявно сборщиком мусора, рекомендуется использовать неявные области только в тех случаях, когда производительность выделения памяти не является критической, чтобы избежать ненужного давления на память.
Возвращает:
новую неявную область.

globalScope

static ResourceScope globalScope()
Возвращает неявную область, которая предполагается всегда активной.
Возвращает:
глобальную область.

© 1993, 2021, 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/17/docs/api/jdk.incubator.foreign/jdk/incubator/foreign/ResourceScope.html

Spec-Zone.ru

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