Spec-Zone.ru › OpenJDK 8

Интерфейс Spliterator<T>

Параметры типа:
T - тип элементов, возвращаемых этим Spliterator
Все известные подинтерфейсы:
Spliterator.OfDouble, Spliterator.OfInt, Spliterator.OfLong, Spliterator.OfPrimitive<T,T_CONS,T_SPLITR>
Все известные реализующие классы:
Spliterators.AbstractDoubleSpliterator, Spliterators.AbstractIntSpliterator, Spliterators.AbstractLongSpliterator, Spliterators.AbstractSpliterator

public interface Spliterator<T>

Объект для обхода и разбиения элементов источника. Источником элементов, покрываемых Spliterator, может быть, например, массив, Collection, канал ввода-вывода или функция генерации.

Spliterator может обходить элементы по одному (tryAdvance()) или последовательно в блоках (forEachRemaining()).

Spliterator также может разбить некоторые свои элементы (используя trySplit()) в другой Spliterator, который может использоваться в потенциально параллельных операциях. Операции с Spliterator, который не может разделиться или делает это очень несбалансированно или неэффективно, вряд ли будут извлекать выгоду из параллелизма. Обход и разделение исчерпывают элементы; каждый Spliterator полезен только для одного объёмного вычисления.

Spliterator также сообщает набор characteristics() своей структуры, источника и элементов из ORDERED, DISTINCT, SORTED, SIZED, NONNULL, IMMUTABLE, CONCURRENT и SUBSIZED. Эти данные могут быть использованы клиентами Spliterator для управления, специализации или упрощения вычислений. Например, Spliterator для Collection сообщит SIZED, Spliterator для Set сообщит DISTINCT, а Spliterator для SortedSet также сообщит SORTED. Характеристики сообщаются как простой объединённый набор битов. Некоторые характеристики дополнительно ограничивают поведение метода; например, если ORDERED, методы обхода должны соответствовать документированному порядку. В будущем могут быть определены новые характеристики, поэтому разработчики не должны присваивать значения неописанным значениям.

Ожидается, что Spliterator, который не сообщает IMMUTABLE или CONCURRENT, будет иметь документированную политику относительно того, когда Spliterator связывается с источником элементов, и обнаружения структурных вмешательств в источник элементов, обнаруженных после связывания. Позднесвязываемый Spliterator связывается с источником элементов в момент первого обхода, первого разделения или первого запроса оценки размера, а не в момент создания Spliterator. Spliterator, который не является позднесвязываемым, связывается с источником элементов в момент создания или первого вызова любого метода. Изменения, внесённые в источник до связывания, отражаются при обходе Spliterator. После связывания Spliterator должен по возможности выбрасывать ConcurrentModificationException, если обнаружено структурное вмешательство. Такие Spliterators называются быстродействующими. Метод объёмного обхода (forEachRemaining()) Spliterator может оптимизировать обход и проверить структурные вмешательства после обхода всех элементов, а не проверять каждый элемент и немедленно завершать.

Spliterator может предоставить оценку количества оставшихся элементов через метод estimateSize(). В идеале, как отражено в характеристике SIZED, это значение точно соответствует количеству элементов, которые будут встречены при успешном обходе. Однако, даже когда оно не известно точно, оценочное значение может быть полезным для операций, выполняемых над источником, например, для определения того, предпочтительнее ли дальнейшее разделение или последовательное обход оставшихся элементов.

Несмотря на очевидную полезность в параллельных алгоритмах, Spliterators не ожидаются быть потокобезопасными; вместо этого реализации параллельных алгоритмов, использующие Spliterators, должны гарантировать, что Spliterator используется только одной нитью за раз. Это, как правило, легко достигается с помощью сериального потокового ограничения, что часто является естественным следствием типичных параллельных алгоритмов, которые работают путём рекурсивного разложения. Нить, вызывающая trySplit(), может передать возвращённый Spliterator другой нити, которая, в свою очередь, может обходить или дополнительно разделять этот Spliterator. Поведение разделения и обхода не определено, если две или более нити одновременно работают с одним Spliterator. Если исходная нить передаёт Spliterator другой нити для обработки, лучше, если эта передача произойдёт до потребления любых элементов с помощью tryAdvance(), так как определённые гарантии (такие как точность estimateSize() для SIZED Spliterators) действительны только до начала обхода.

Предоставляются специализированные подтипы Spliterators для int, long и double значений. Подтипы по умолчанию реализуют tryAdvance(java.util.function.Consumer) и forEachRemaining(java.util.function.Consumer) для упаковки примитивных значений в экземпляры соответствующего обертывающего класса. Такое преобразование может подорвать любые преимущества производительности, полученные при использовании примитивных специализаций. Для избежания упаковки следует использовать соответствующие примитивные методы. Например, Spliterator.OfInt.tryAdvance(java.util.function.IntConsumer) и Spliterator.OfInt.forEachRemaining(java.util.function.IntConsumer) следует использовать вместо Spliterator.OfInt.tryAdvance(java.util.function.Consumer) и Spliterator.OfInt.forEachRemaining(java.util.function.Consumer). Обход примитивных значений с помощью методов упаковки tryAdvance() и forEachRemaining() не влияет на порядок, в котором значения, преобразованные в упакованные значения, встречаются.

Примечание к API:

Spliterators, подобно Iterators, предназначены для обхода элементов источника. API Spliterator был разработан для поддержки эффективного параллельного обхода в дополнение к последовательному обходу, поддерживая разложение, а также итерацию по одному элементу. Кроме того, протокол доступа к элементам через Spliterator предназначен для наложения меньшей накладных расходов на элемент, чем Iterator, и для избежания присущей гонки, возникающей при наличии отдельных методов для hasNext() и next().

Для изменяемых источников произвольное и недетерминированное поведение может произойти, если источник подвергнется структурному вмешательству (добавление, замена или удаление элементов) между временем связывания Spliterator с его источником данных и концом обхода. Например, такое вмешательство приведёт к произвольным и недетерминированным результатам при использовании фреймворка java.util.stream.

Структурное вмешательство в источник можно управлять следующими способами (в приблизительном порядке убывания желательности):

  • В источник невозможно внести структурные изменения.
    Например, экземпляр CopyOnWriteArrayList является неизменяемым источником. Spliterator, созданный из источника, сообщает характеристику IMMUTABLE.
  • Источник управляет одновременными модификациями.
    Например, набор ключей ConcurrentHashMap является конкуретным источником. Spliterator, созданный из источника, сообщает характеристику CONCURRENT.
  • Изменяемый источник предоставляет Spliterator с поздним связыванием и быстрым отказом.
    Позднее связывание сужает окно, в течение которого вмешательство может повлиять на вычисление; быстрый отказ обнаруживает, по возможности, что структурное вмешательство произошло после начала обхода и выбрасывает ConcurrentModificationException. Например, ArrayList и многие другие неконкурентные Collection классы в JDK предоставляют Spliterator с поздним связыванием и быстрым отказом.
  • Изменяемый источник предоставляет Spliterator с не-поздним связыванием, но быстрым отказом.
    Источник увеличивает вероятность выброса ConcurrentModificationException поскольку окно потенциальных вмешательств больше.
  • Изменяемый источник предоставляет Spliterator с поздним связыванием и не-быстрым отказом.
    Источник рискует произвольным недетерминированным поведением после начала обхода, поскольку вмешательство не обнаруживается.
  • Изменяемый источник предоставляет Spliterator с не-поздним связыванием и не-быстрым отказом.
    Источник увеличивает риск произвольного недетерминированного поведения, поскольку не обнаруженное вмешательство может произойти после создания.

Пример. Вот класс (не очень полезный, кроме как для иллюстрации), который поддерживает массив, в котором фактические данные хранятся в чётных позициях, а несвязанные данные тега хранятся в нечётных позициях. Его Spliterator игнорирует теги.

class TaggedArray<T> {
   private final Object[] elements; // immutable after construction
   TaggedArray(T[] data, Object[] tags) {
     int size = data.length;
     if (tags.length != size) throw new IllegalArgumentException();
     this.elements = new Object[2 * size];
     for (int i = 0, j = 0; i < size; ++i) {
       elements[j++] = data[i];
       elements[j++] = tags[i];
     }
   }

   public Spliterator<T> spliterator() {
     return new TaggedArraySpliterator<>(elements, 0, elements.length);
   }

   static class TaggedArraySpliterator<T> implements Spliterator<T> {
     private final Object[] array;
     private int origin; // current index, advanced on split or traversal
     private final int fence; // one past the greatest index

     TaggedArraySpliterator(Object[] array, int origin, int fence) {
       this.array = array; this.origin = origin; this.fence = fence;
     }

     public void forEachRemaining(Consumer<? super T> action) {
       for (; origin < fence; origin += 2)
         action.accept((T) array[origin]);
     }

     public boolean tryAdvance(Consumer<? super T> action) {
       if (origin < fence) {
         action.accept((T) array[origin]);
         origin += 2;
         return true;
       }
       else // cannot advance
         return false;
     }

     public Spliterator<T> trySplit() {
       int lo = origin; // divide range in half
       int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even
       if (lo < mid) { // split out left half
         origin = mid; // reset this Spliterator's origin
         return new TaggedArraySpliterator<>(array, lo, mid);
       }
       else       // too small to split
         return null;
     }

     public long estimateSize() {
       return (long)((fence - origin) / 2);
     }

     public int characteristics() {
       return ORDERED | SIZED | IMMUTABLE | SUBSIZED;
     }
   }
 }

В качестве примера того, как фреймворк параллельных вычислений, такой как пакет java.util.stream, будет использовать Spliterator в параллельном вычислении, вот один способ реализации связанного параллельного forEach, который иллюстрирует основной способ использования – разделение подзадач до тех пор, пока объём работы не станет достаточно малым, чтобы выполнение было последовательным. Здесь мы предполагаем, что порядок обработки в подзадачах не имеет значения; разные (разветвлённые) задачи могут дополнительно разделяться и обрабатывать элементы конкурирующим образом в неопределённом порядке. В этом примере используется CountedCompleter; аналогичные примеры применимы к другим построениям параллельных задач.

static <T> void parEach(TaggedArray<T> a, Consumer<T> action) {
   Spliterator<T> s = a.spliterator();
   long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8);
   new ParEach(null, s, action, targetBatchSize).invoke();
 }

 static class ParEach<T> extends CountedCompleter<Void> {
   final Spliterator<T> spliterator;
   final Consumer<T> action;
   final long targetBatchSize;

   ParEach(ParEach<T> parent, Spliterator<T> spliterator,
           Consumer<T> action, long targetBatchSize) {
     super(parent);
     this.spliterator = spliterator; this.action = action;
     this.targetBatchSize = targetBatchSize;
   }

   public void compute() {
     Spliterator<T> sub;
     while (spliterator.estimateSize() > targetBatchSize &&
            (sub = spliterator.trySplit()) != null) {
       addToPendingCount(1);
       new ParEach<>(this, sub, action, targetBatchSize).fork();
     }
     spliterator.forEachRemaining(action);
     propagateCompletion();
   }
 }
Примечание к реализации:
Если булевая системная переменная org.openjdk.java.util.stream.tripwire установлена в значение true, то будут сообщены диагностические предупреждения, если произойдёт упаковка примитивных значений при работе с примитивными специализациями.
С:
1.8
См. также:
Collection

Вложенные классы

Модификатор и тип Интерфейс и описание
static interface  Spliterator.OfDouble

Специализированный Spliterator для значений double.

static interface  Spliterator.OfInt

Специализированный Spliterator для значений int.

static interface  Spliterator.OfLong

Специализированный Spliterator для значений long.

static interface  Spliterator.OfPrimitive<T,T_CONS,T_SPLITR extends Spliterator.OfPrimitive<T,T_CONS,T_SPLITR>>

Специализированный Spliterator для примитивных значений.

Поля

Модификатор и тип Поле и описание
static int CONCURRENT

Значение характеристики, указывающее, что источник элементов может быть безопасно изменён параллельно (разрешая добавления, замены и/или удаления) несколькими потоками без внешней синхронизации.

static int DISTINCT

Значение характеристики, указывающее, что для каждой пары встреченных элементов x, y, !x.equals(y).

static int IMMUTABLE

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

static int NONNULL

Значение характеристики, указывающее, что источник гарантирует, что встреченные элементы не будут null.

static int ORDERED

Значение характеристики, указывающее, что порядок встречи элементов определён.

static int SIZED

Значение характеристики, указывающее, что значение, возвращённое из estimateSize() до обхода или разделения, представляет конечный размер, который в отсутствие структурных изменений источника представляет точный подсчёт количества элементов, которые будут встречены полным обходом.

static int SORTED

Значение характеристики, указывающее, что порядок встречи следует определённому порядку сортировки.

static int SUBSIZED

Значение характеристики, указывающее, что все Spliterator, полученные из trySplit(), будут как SIZED, так и SUBSIZED.

Методы

Модификатор и тип Метод и описание
int characteristics()

Возвращает набор характеристик этого Spliterator и его элементов.

long estimateSize()

Возвращает оценку количества элементов, которые будут встречены при обходе с помощью forEachRemaining(java.util.function.Consumer<? super T>), или возвращает Long.MAX_VALUE, если бесконечно, неизвестно или слишком дорого вычисляется.

default void forEachRemaining(Consumer<? super T> action)

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

default Comparator<? super T> getComparator()

Если источник этого Spliterator SORTED по Comparator, возвращает этот Comparator.

default long getExactSizeIfKnown()

Удобный метод, который возвращает estimateSize(), если этот Spliterator SIZED, иначе -1.

default boolean hasCharacteristics(int characteristics)

Возвращает true , если характеристики этого Spliterator characteristics() содержат все заданные характеристики.

boolean tryAdvance(Consumer<? super T> action)

Если существует оставшийся элемент, выполняет заданное действие над ним, возвращая true; в противном случае возвращает false.

Spliterator<T> trySplit()

Если этот spliterator может быть разделён, возвращает Spliterator, охватывающий элементы, которые, по возвращении из этого метода, не будут охватываться этим Spliterator.

Поля

ORDERED

static final int ORDERED

Характеристическое значение, указывающее, что порядок встречи элементов для элементов определён. В таком случае этот Spliterator гарантирует, что метод trySplit() разделяет строгий префикс элементов, что метод tryAdvance(java.util.function.Consumer<? super T>) переходит к одному элементу в порядке префикса, и что forEachRemaining(java.util.function.Consumer<? super T>) выполняет действия в порядке встречи.

У Collection есть порядок встречи, если соответствующий Collection.iterator() документирует порядок. В таком случае порядок встречи совпадает с документированным порядком. В противном случае у коллекции нет порядка встречи.

Примечание API:
Порядок встречи гарантированно является восходящим порядком индексов для любого List. Но порядок не гарантируется для основанных на хэшировании коллекций, таких как HashSet. Клиенты Spliterator, который сообщает ORDERED, должны сохранять ограничения порядка в некоммутативных параллельных вычислениях.
См. также:
Значения постоянных полей

DISTINCT

static final int DISTINCT

Характеристическое значение, указывающее, что для каждой пары встреченных элементов x, y, !x.equals(y). Это относится, например, к Spliterator, основанному на Set.

См. также:
Значения постоянных полей

SORTED

static final int SORTED

Характеристическое значение, указывающее, что порядок встречи соответствует определённому порядку сортировки. В таком случае метод getComparator() возвращает связанный Comparator, или null если все элементы являются Comparable и отсортированы по их естественному порядку.

Spliterator, который сообщает SORTED должен также сообщать ORDERED.

Примечание API:
Spliterators для Collection классов в JDK, которые реализуют NavigableSet или SortedSet сообщают SORTED.
См. также:
Значения постоянных полей

SIZED

static final int SIZED

Характеристическое значение, указывающее, что возвращаемое значение из estimateSize() перед обходом или разделением представляет конечный размер, который, в отсутствие структурных изменений источника, представляет точный подсчёт числа элементов, которые будут встречены при полном обходе.

Примечание API:
Большинство Spliterators для коллекций, которые покрывают все элементы коллекции Collection, сообщают об этой характеристике. Под-Spliterators, такие как для HashSet, которые покрывают подмножество элементов и приближают свой размер, не сообщают.
См. также:
Значения постоянных полей

NONNULL

static final int NONNULL

Характеристическое значение, указывающее, что источник гарантирует, что встречаемые элементы не будут null. (Это относится, например, к большинству конкурентных коллекций, очередям и картам.)

См. также:
Значения постоянных полей

IMMUTABLE

static final int IMMUTABLE

Характеристическое значение, указывающее, что источник элементов не может быть структурно изменён; то есть элементы нельзя добавить, заменить или удалить, поэтому такие изменения не могут произойти во время обхода. Spliterator, который не сообщает IMMUTABLE или CONCURRENT должен иметь документированную политику (например, выбрасывать ConcurrentModificationException) в случае обнаружения структурного вмешательства во время обхода.

См. также:
Значения постоянных полей

CONCURRENT

static final int CONCURRENT

Характеристическое значение, указывающее, что источник элементов может быть безопасно изменён одновременно (разрешая добавление, замену и/или удаление) несколькими потоками без внешней синхронизации. В таком случае от Spliterator ожидается документированная политика относительно влияния модификаций во время обхода.

Уровневый Spliterator не должен сообщать как CONCURRENT, так и SIZED, так как конечный размер, если известен, может измениться, если источник изменяется одновременно во время обхода. Такой Spliterator несогласован, и никакие гарантии не могут быть даны относительно любого вычисления, использующего этот Spliterator. Под-Spliterators могут сообщать SIZED если размер под-разбиения известен и добавление или удаление в источнике не отражается при обходе.

Примечание API:
Большинство конкурирующих коллекций поддерживают политику согласованности, гарантирующую точность в отношении элементов, присутствующих в момент создания Spliterator, но, возможно, не отражающих последующие добавления или удаления.
См. также:
Значения постоянных полей

SUBSIZED

static final int SUBSIZED

Характеристическое значение, указывающее, что все Spliterators, полученные из trySplit(), будут и SIZED, и SUBSIZED. (Это означает, что все дочерние Spliterators, прямые или косвенные, будут SIZED.)

Spliterator, который не сообщает SIZED как требуется SUBSIZED, несогласован, и никакие гарантии не могут быть даны относительно любого вычисления, использующего этот Spliterator.

Примечание API:
Некоторые Spliterators, такие как основной Spliterator для примерно сбалансированного двоичного дерева, будут сообщать SIZED, но не SUBSIZED, так как часто известно количество элементов всего дерева, но не точные размеры поддеревьев.
См. также:
Значения постоянных полей

Методы

tryAdvance

boolean tryAdvance(Consumer<? super T> action)

Если оставшийся элемент существует, выполняет заданное действие над ним, возвращая true; в противном случае возвращает false. Если этот Spliterator является ORDERED, действие выполняется над следующим элементом в порядке встречи. Исключение, брошенное действием, передаётся вызывающему объекту.

Параметры:
action - Действие
Возвращает:
false если в методе не было оставшихся элементов при входе, иначе true.
Исключения:
NullPointerException - если указанное действие равно null

forEachRemaining

default void forEachRemaining(Consumer<? super T> action)

Выполняет заданное действие для каждого оставшегося элемента последовательно в текущем потоке, до тех пор, пока все элементы не будут обработаны или действие не выбросит исключение. Если этот Spliterator является ORDERED, действия выполняются в порядке встречи. Исключение, брошенное действием, передаётся вызывающему объекту.

Требования к реализации:
По умолчанию реализация многократно вызывает tryAdvance(java.util.function.Consumer<? super T>), пока не вернёт false. Она должна быть переопределена, когда это возможно.
Параметры:
action - Действие
Исключения:
NullPointerException - если указанное действие равно null

trySplit

Spliterator<T> trySplit()

Если этот Spliterator может быть разделён, возвращает Spliterator, охватывающий элементы, которые после возврата из этого метода не будут охватываться этим Spliterator.

Если этот Spliterator является ORDERED, возвращаемый Spliterator должен охватывать строгий префикс элементов.

Если этот Spliterator не охватывает бесконечное число элементов, повторные вызовы trySplit() должны в конечном итоге вернуть null. После возврата не нулевого значения:

  • значение, отчётённое для estimateSize() до разделения, должно после разделения быть больше или равно estimateSize() для этого и возвращаемого Spliterator; и
  • если этот Spliterator является SUBSIZED, тогда estimateSize() для этого Spliterator до разделения должен быть равен сумме estimateSize() для этого и возвращаемого Spliterator после разделения.

Этот метод может возвратить null по любой причине, включая пустоту, невозможность разделения после начала обхода, ограничения структуры данных и соображения эффективности.

Примечание API:
Идеальный метод trySplit эффективно (без обхода) делит свои элементы точно пополам, что позволяет сбалансированное параллельное вычисление. Многие отклонения от этого идеала остаются высокоэффективными; например, только приблизительное разделение приблизительно сбалансированного дерева или для дерева, в котором листья могут содержать либо один, либо два элемента, не пытаясь дополнительно разделять эти узлы. Однако большие отклонения в балансе и/или чрезмерно неэффективные механизмы trySplit обычно приводят к плохой параллельной производительности.
Возвращает:
Spliterator, охватывающий часть элементов, или null если этот Spliterator не может быть разделён

estimateSize

long estimateSize()

Возвращает оценку количества элементов, которые будут встречены при обходе с помощью forEachRemaining(java.util.function.Consumer<? super T>), или возвращает Long.MAX_VALUE если бесконечно, неизвестно или слишком дорого вычислить.

Если этот Spliterator является SIZED и ещё не был частично пройден или разделён, или этот Spliterator является SUBSIZED и ещё не был частично пройден, эта оценка должна быть точным количеством элементов, которые будут встречены при полном обходе. В противном случае эта оценка может быть произвольно неточной, но должна уменьшаться, как указано, при вызовах trySplit().

Примечание API:
Даже приблизительная оценка часто полезна и недорога в вычислении. Например, под-разделитель приблизительно сбалансированного бинарного дерева может возвращать значение, которое оценивает число элементов, равное половине от числа элементов родительского элемента; если корневой разделитель не поддерживает точный счёт, он может оценить размер как степень двойки, соответствующую максимальной глубине.
Возвращает:
оценённый размер или Long.MAX_VALUE, если бесконечен, неизвестен или слишком дорого вычисляется.

getExactSizeIfKnown

default long getExactSizeIfKnown()

Удобный метод, возвращающий estimateSize(), если этот разделитель SIZED, иначе -1.

Требования к реализации:
По умолчанию реализация возвращает результат estimateSize(), если разделитель сообщает о характеристике SIZED, и -1 в противном случае.
Возвращает:
точный размер, если известен, иначе -1.

characteristics

int characteristics()

Возвращает набор характеристик этого разделителя и его элементов. Результат представлен как побитовое ИЛИ значений из ORDERED, DISTINCT, SORTED, SIZED, NONNULL, IMMUTABLE, CONCURRENT, SUBSIZED. Повторные вызовы characteristics() для данного разделителя до или между вызовами trySplit должны всегда возвращать тот же результат.

Если разделитель сообщает о несогласованном наборе характеристик (как при единственном вызове, так и при нескольких вызовах), никакие гарантии о вычислениях с использованием этого разделителя не могут быть даны.

Примечание API:
Характеристики данного разделителя перед разделением могут отличаться от характеристик после разделения. Для конкретных примеров см. значения характеристик SIZED, SUBSIZED и CONCURRENT.
Возвращает:
представление характеристик

hasCharacteristics

default boolean hasCharacteristics(int characteristics)

Возвращает true, если характеристики этого разделителя characteristics() содержат все заданные характеристики.

Требования к реализации:
По умолчанию реализация возвращает true, если соответствующие биты заданных характеристик установлены.
Параметры:
characteristics - проверяемые характеристики
Возвращает:
true если все указанные характеристики присутствуют, иначе false

getComparator

default Comparator<? super T> getComparator()

Если источник этого разделителя SORTED по Comparator, возвращает этот Comparator. Если источник SORTED в естественном порядке, возвращает null. В противном случае, если источник не SORTED, выбрасывает IllegalStateException.

Требования к реализации:
По умолчанию реализация всегда выбрасывает IllegalStateException.
Возвращает:
Comparator или null, если элементы отсортированы в естественном порядке.
Выбрасывает:
IllegalStateException - если разделитель не сообщает о характеристике SORTED.

© 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.

Spec-Zone.ru

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