Spec-Zone .ru
спецификации, руководства, описания, API
Содержание документации
 

Pack200: Упакованный Формат Развертывания Класса Для Приложений Java™

ОСНОВНАЯ ВЕРСИЯ: http://docs.oracle.com/javase/6/docs/technotes/guides/pack200/pack-spec.html

Содержание

История версии

Изменения, произведенные для JSR 292 августа 2011 поддержки

Изменения, произведенные для MR #1 01-Jun-2005

Изменения, произведенные для MR #1 20-Apr-2005



1. Введение

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

Этот формат позволяет любому числу (от одного до сотен тысяч) классов Java быть закодированным компрессором, переданным сжато в единственном блоке байтов, и декодировал декомпрессором в эквивалентный Java файлы class. Поскольку это может также представить ресурсы class и другие "файлы стороны", это может служить альтернативой архиву JAR для некоторых задач развертывания, особенно загружая приложения Java.

Формат Pack200 может уменьшить размер приложения Java фактором семь - девять, по сравнению с эквивалентным JAR, содержащим несжатый, хранил файлы class. В отличие от этого, использование zip ВЫКАЧИВАЕТ интеграл алгоритма к JAR, и архивы ZIP получает фактор два. Недокументированный механизм "уплотнения", используемый, чтобы развернуть загрузки SDK в прошлом, получает соответствующий фактор пять - шесть. Отметьте, что все эти числа принимают и соединяются, эффекты постпередачи с ВЫКАЧИВАЮТ или подобный стандартный алгоритм сжатия. (ВЫКАЧАЙТЕ, документируется здесь.)

Основное побуждение для этого формата должно уменьшить диск и требования пропускной способности для упаковки приложения Java, передачи, и поставки. Более ранняя версия использовалась, чтобы упаковать загрузки для Java 2 Standard Edition выпуск 1.4.1 и 1.4.2 (кодовые названия "Загрузочный лоток" и "Богомол").

Этот формат не предназначается для быстрой загрузки в виртуальную машину, и не пытается улучшить скорость запуска или объем потребляемой памяти в запущении приложений Java. Тяжелые технические требования к непосредственно загружаемому формату файла сделали бы оптимальное сжатие невозможным. Декомпрессор настойчиво сжатого файла будет иметь сложное задание, чтобы сделать, и должен быть позволен память и процессорное время, чтобы сделать это задание. Мы предполагаем, что архивы Pack200 будут распакованы на тех же самых классах машины, которые выполняют Java SE и приложения J2EE.

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

Этот формат не пытается копировать работу, выполняемую, ВЫКАЧИВАЮТ или другие байтовые алгоритмы сжатия. Как правило, инструменты используя Pack200 далее сожмут архивы, храня их в файлах ZIP или используя некоторый другой метод сжатия. Присутствие такого компрессора постпередачи является предположением, сделанным проектом Pack200.

Эта спецификация сложна, и может замеченный некоторым читателям, напрасно сложным. Проектные решения, отраженные здесь, были мотивированы обширным тестированием и экспериментированием с фактическим Java файлы class, найденные в реальных продуктах. Попытка удалить сложность из этой спецификации вероятна также удалить в известной мере существенную эффективность сжатия.

2. Вводы архива

Архив Pack200, как файл JAR, переносит изображения файлов class и другого ("ресурс") файлы, расположенные в иерархической структуре каталога.

Никакое специальное сжатие или преобразование не выполняются ни на каком файле кроме файлов class кроме (возможно) переупорядочения их типом файла. Компрессор постпередачи, как предполагается, обеспечивает соответствующее сжатие на тех промежутках архива, которые переносят изображения non-class файлов.

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

Отметьте, что каждый файл class должен быть полностью проанализирован компрессором, так, чтобы весь постоянный пул индексировал, может быть найден и (позже) перенумерован. Это требование применяется к любому class, полю, методу, или атрибуту кода, который обращается к константе. Формат Pack200 поддерживает умеренный диапазон атрибутов. Скромное разнообразие новых разметок атрибута может быть объявлено к компрессору, и формат Pack200 обеспечивает место, чтобы передать такие разметки для использования декомпрессорами.

3. Сводка Структуры Архивного файла

Архивный файл состоит из короткого заголовка архива, сопровождаемого многими независимыми разделами файлов, названными полосами. (Есть приблизительно 100 из них; это число может измениться.) Каждая полоса передает массив маленьких целых чисел, названных элементами полосы. После заголовка архива архив состоит только из полос.

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

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

У элементов любой данной полосы есть общее значение и роль. Например, имена всех переданных классов находятся в единственной полосе, в то время как все количества поля class находятся в различной полосе. Каждая полоса передается как непрерывный сегмент байтов в пределах архива. Эта смежность является главной причиной, что Pack200 архив, в то время как уплотнено для начала, очень сжимаем утилитами как zip.

В некоторых полосах каждый элемент помогает описать один объект. Например, каждый class связывается с количеством полей, которое дается в архиве как соответствующее значение в полосе class_field_count. В других полосах один объект может быть описан выполнением нуля или большего количества элементов в полосе. Например, интерфейсы, реализованные class, даются в архиве как соответствующее выполнение нуля или большего количества значений в полосе class_interface; каждое такое значение является индексировать обращением к единственному class.

Очень немного полос (меньше чем 10) содержат негомогенные байты, такие как изображения файлов ресурсов. Они немногих вызывают полосами байта. Многие из полос содержат ссылки в постоянный пул. Некоторые содержат флаги модификатора доступа и связанные биты. Одна полоса, названная полосой случайной работы, содержит строковые символы в особенно выбранном кодировании под названием "CHAR3" (несколько родственный UTF8, но не идентичный). Остальная часть полос передает целые числа со множеством других интерпретаций.

Одна из целочисленных полос (cp_Utf8_big_chars) переносит символы единственной строки CONSTANT_Utf8, выбранной для специального режима. Уникально, эта полоса повторяется нуль или больше раз, в зависимости от того, сколько строк выбирается для этого специального режима. (Эти особенно переданные "большие строки" объясняются позже в этом документе.)

У большинства полос есть легко понятая функция, такая как передача числа методов в class, или имени поля, или операнда "getfield" инструкции байт-кода.

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

4. Введение в Целочисленные Кодировки

Каждая полоса использует одну или более тактик кодирования, чтобы закодировать ее элементы как последовательности байтов. (Компрессор постпередачи, как ожидают, превратит эти байты в последовательности битов, но его действия не определяются этим документом.) Компрессор Pack200 свободен выбрать и изменить тактику кодирования, используемую полосой. Тактика кодирования, используемая в одной полосе, независима от используемых в других полосах. Пространство поддерживаемой тактики кодирования является важной частью спецификации Pack200. Существующий раздел представляет эти кодировки, которые определяются подробно позже в этом документе.

Как можно было бы ожидать, полосы байта (которые кодируют bytewise данные, такие как изображения файла ресурсов), кодируют их целые числа как 8-разрядные байты без знака. Это кодирование называют BYTE1 в этой спецификации. (Сравните тип "u1" в определении файла class.)

У других полос есть значения с намного большим динамическим диапазоном, включая (в нескольких случаях) отрицательные числа, и/или значения полностью до 32-разрядного максимума без знака. Большинство этих кодировок является переменной длиной в ожидании, что типичный элемент полосы будет относительно маленьким в величине, даже при том, что некоторые элементы могут быть большими и потребовать, чтобы больше байтов представило. Некоторые полосы, которые, как ожидают, покажут корреляции strong в их последовательностях элемента, кодируются как последовательные различия (кодирование дельты), а не абсолютные числовые значения.

Каждая полоса связывается с основным кодированием, которое компрессор и декомпрессор соглашаются использовать, передавая элементы той полосы. Для любой полосы после конца заголовка сегмента, за исключением полос байта, компрессор может дополнительно определить вторичное кодирование, чтобы использовать вместо основного кодирования. В основном, значения по умолчанию кодирования полосы к основному устройству, если нет явно объявленное вторичное устройство. Это позволяет формату Pack200 адаптироваться более близко к фактической статистике элементов полосы.

Например, у большинства полос, таких как те, которые содержат количества и размеры, есть основное кодирование под названием UNSIGNED5. Это - кодирование без знака общего назначения, которое представляет значения в диапазоне [0.. 191] как единственный байт, и увеличивается к максимальному размеру пяти байтов для чисел, больше чем приблизительно пятьдесят миллионов. Однако, если полоса содержит только числа в диапазоне [0,255], кодирование BYTE1 более компактно, и компрессору позволяют дать декомпрессору команду использовать это вместо этого.

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

4.1. Целочисленная Схема кодировки

Формат Pack200 основан на схеме целочисленных систем кодирования, параметризованных четырьмя числами (B, H, S, D). От этого бесконечного множества приблизительно 10 выбранных кодировок служат основными кодировками для полос, и еще приблизительно 100 служат дополнительными кодировками. Система (B, H, S, D) кодировки объясняется подробно в более позднем разделе. Для текущих целей будет достаточно краткое введение.

Параметр B (1 <=B <=5) является максимальной длиной в байтах кодирования единственного целого числа. Менее существенные биты всегда кодируются в более ранних байтах.

Параметр H (1 <=H <=256) является основанием кодирования. это также определяет условия, при которых завершаются последовательности байта кодирования. Cо-параметр L (0 <=L <=255) определяется как (256-ой). Закодированным последовательностям байта позволяют содержать только один байт со значением меньше чем L, и тот байт должен быть последним в последовательности. Таким образом большие значения H делают для более длительных средних длин кодирования. Если H 256, и L является нулем, то метод кодирования является фиксированной длиной, потому что все кодировки должны быть точно B байтами долго.

Параметр S (0 <=S <=2) определяет, ли и как кодирование представляет числа со знаком. (Более точно, так как элементы полосы традиционно расцениваются, поскольку 32-разрядные целые числа без знака, S определяет кодирование элементов полосы, больше чем самое большое 31-разрядное число без знака, 2147483647. Но мы будем продолжать обращаться к таким числам как отрицательный, где различие не важно.) S обозначает число младших значащих битов, которые служат знаковым битом. Если S является нулем, числа без знака. Если S один, LSB числа без знака является монопольным-ored в смещенный на право остаток от числа без знака, чтобы произвести соответствующее число со знаком. Если S - больше чем один, произведенное число со знаком отрицательно, только если все младшие значащие биты S устанавливаются, и иначе эти младшие биты способствуют положительной величине целого числа. Это представление эффективно для полос, содержащих главным-образом-положительные-числа, такие как смещения ответвления байт-кода. Интерпретация знаковых битов более точно описывается в другом месте.

Параметр D (0 <=D <=1) определяет, передает ли полоса свои данные через последовательные различия (то есть, кодирование дельты). В записи этих кодировок могут быть опущены параметры S и D, если и нуль, и D может быть опущен если нуль.

Таким образом кодирование (1,256,0,0), также записанный как (1 256), представляет числа как байты без знака, в то время как (4 256) представляет числа как 32-разрядные целые числа с прямым порядком байтов без знака. Кодирование (1,256,1) карты единственные байты к числам в диапазоне [-128 127]. Кодирование (1,256,1,1) экспрессы любая последовательность чисел, последовательные различия которых находятся в диапазоне [-128 127] (и чье первое число находится в том диапазоне).

Очень общее кодирование UNSIGNED5 может представить полный диапазон без знака 32-разрядных целых чисел. Последовательность байта в этом кодировании состоит или из четырех байтов меньше чем 192 сопровождаемые произвольным байтом, или иначе от нуля до трех байтов меньше чем 192 сопровождаемые байтом, больше чем или равный 192. Значение без знака формируется, масштабируя каждый последующий байт последовательными полномочиями основания 64, и добавляя все масштабируемые значения байта вместе.

значение байт 0 байт 1 байт 2 байт 3 байт 4
1 1        
191 191        
192 192 0      
193 193 0      
255 255 0      
256 192 1      
512 192 5      
1024 192 13      
2048 192 29      
12479 255 191      
12480 192 192 0    
798911 255 255 191    
798912 192 192 192 0  
51130559 255 255 255 191  
51130560 192 192 192 192 0
0xFFFFFFFF 255 252 252 252 252

Вот набор основных кодировок, используемых по крайней мере одной полосой:

Ввести Имя Цель
(1,256) BYTE1 байты
(3,128) CHAR3 Символы Java
(5,4) BCI5 позиции байт-кода
(5,4,2) BRANCH5 смещения ответвления байт-кода
(5,64) UNSIGNED5 общий ints без знака
(5,64,1) SIGNED5 общий подписал ints
(5,64,0,1) UDELTA5 монотонные последовательности
(5,64,1,1) DELTA5 автокоррелированые последовательности
(5,64,2,1) MDELTA5 главным образом монотонные последовательности

5. Определения полосы

Файл в целом состоит приблизительно из 200 полос в четырех главных группах. После заголовка постоянное содержание пула на первом месте, сопровождаемое большей частью схемы class, сопровождаемой консолидацией всей информации атрибута (для классов, полей, методов, кодов, и архива в целом), и заканчивающийся байт-кодами для всех методов.

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

  pack200_segment:
        segment_header
        *band_headers :BYTE1
        cp_bands
        attr_definition_bands
        ic_bands
        class_bands
        bc_bands
        file_bands
 

Терминалы этой грамматики являются скалярами и полосами. Чтобы сделать терминалы легче распознать, скалярные имена начинаются со знака фунта "#", и названия группы начинаются со звезды "*". Скаляр является закодированным целым числом (или маленькое постоянное число их), который появляется в пределах заголовка архивного файла. Когда скаляр упоминается в грамматике, он сопровождается двоеточием и кодированием и заключенным в скобки количеством скалярного значения (й). Всякий раз, когда полоса упоминается, она сопровождается двоеточием и его основным кодированием, сопровождаемым комментарием в квадратных скобках, указывающих на его длину. Если полоса кодирует ссылки в некоторую другую структуру данных, такие как постоянный пул, та структура упоминается как комментарий в круглых скобках. Если ссылкам позволяют быть нулем, тот факт упоминается также.

Вот пример:

  example_non_terminal:
        other_non_terminal
        #single_scalar_integer :UNSIGNED5[1]
        #four_byte_scalar :BYTE1[4]
        *band_of_integers :UNSIGNED5 [#integer_count]
        *band_of_method_references :UNSIGNED5 [SUM(*ref_counts)] (cp_Method)
        *band_of_strings_and_nulls :UNSIGNED5 [...] (null or cp_String)
 

Многие из длин полосы являются просто ссылками на предыдущие скаляры (такие как [#class_count]) или суммы предыдущих полос, которые передают количества (например, [SUM(*class_method_count)]). Эти заключенные в скобки длины должны быть расценены как комментарии в грамматике, так как текст спецификации определяет длины полосы устно. Количества полосы, которые не могут быть кратко получены в итоге как иногда определено в частичном выражении, которое содержит замещающий знак.

Иногда мы используем дополнительные грамматические нотации. Мы используем обычные операторы регулярного выражения средства (X | Y), достойные или X или Y, (X)* означает любое число соответствий для X, (X)+ означает одно или более соответствий для X, и (X)? означает или достойный X или ничто. В одном случае, где у полосы может быть несколько экземпляров, выражение (band1)  , длина ** (band2) означает, что есть так много экземпляров band1, как есть элементы в band2. Аналогично, в трех случаях, выражение (band1)  ** #scalar указывает, что есть нуль или экземпляры band1 согласно значению (нуль или один, соответственно) булева скалярного значения.

5.1. Сегментация архива

Весь формат архива Pack200 может быть повторен один или более раз в передаче к декомпрессору. В этом случае каждый полный набор переданных полос полос просматривается как сегмент целой передачи. Декомпрессор обязан принимать многократные сегменты, и обрабатывать каждый сегмент независимо в порядке. Выходные файлы, следующие из каждого сегмента, накапливаются в порядке. Если декомпрессор производит файл JAR, многократные сегменты должны быть накоплены в один выходной файл JAR, элементы которого составляются из соответствующих элементов, переданных в каждом сегменте в порядке.
  pack200_archive:
        (pack200_segment)+
 
Отметьте, что каждый сегмент начинается снова с магического числа Pack200 и номеров версий.

(С одним протестом это означает, что архивы Pack200 могут быть связаны с естественным значением объединения архивов, которые они представляют. Как будет замечен ниже, если поле #archive_size не будет присутствовать в каждом заголовке сегмента, оно должно быть вставлено прежде, чем другой сегмент добавляется, так, чтобы декомпрессор мог найти конец каждого сегмента. Формат заголовка сегмента является так, что этой корректировкой, может быть сделан легко.)

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

Сегментация может также помочь решить масштабирующуюся проблему с очень большими архивами (многих десятков мегабайтов), в котором width индексирует в объединенные глобальные постоянные пулы, может вырасти вне преимуществ глобального постоянного совместного использования. Запуская новый сегмент, компрессор сбрасывает постоянные пулы декомпрессора, убирая бесполезные константы, за счет повторного заявления о константах, которые находятся все еще в использовании. (Компромиссы подобны в разновидности проекту копирования сборщиков "мусора".)

5.2. Заголовок архива

Заголовок состоит из магического числа и информации о версии, в формате точно параллельны к Java формату файла class. Однако, помимо магического числа, в формате Pack200 нет никаких других целых чисел с обратным порядком байтов. Все целочисленные кодировки в полосах представляют арифметически менее - существенные биты сначала.

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

  segment_header:
        archive_magic archive_header

  archive_magic:
        #archive_magic_word :BYTE1[4]

  archive_header:
        #archive_minver :UNSIGNED5[1]
        #archive_majver :UNSIGNED5[1]
        #archive_options :UNSIGNED5[1]
        (archive_file_counts) ** (#have_file_headers)
        (archive_special_counts) ** (#have_special_formats)
        cp_counts
        class_counts

  archive_file_counts:
        #archive_size_hi :UNSIGNED5[1]
        #archive_size_lo :UNSIGNED5[1]
        #archive_next_count :UNSIGNED5[1]
        #archive_modtime :UNSIGNED5[1]
        #file_count :UNSIGNED5[1]
 

archive_magic_word состоит из четырех байтов 0xCA, 0xFE, 0xD0, 0x0D. #archive_minver должен быть номером 1. #archive_majver должен быть номером 170. Оба из последних двух значений могут быть постепенно увеличены в будущем, чтобы отразить маленькие версии в этом формате файла. Отметьте, что в предыдущих версиях этого стандарта, номера вспомогательной версии и номера основной версии были 7 и 150, или 1 и 160.

Заголовок также содержит начальные количества постоянных записей пула и других "высокоуровневых" объектов. Все эти количества даются в формате UNSIGNED5. Некоторые из этих количеств условно присутствуют, управляемые битами в слове #archive_options. Правило для недостающего значения заголовка (и для отсутствующих значений вообще если иначе не определено) состоит в том, что декомпрессор должен вести себя, как будто он получил явное нулевое значение.

5.2.1. Опции архива и Свойства Файла

Слово #archive_options интерпретируется поразрядное. Определенным битам дают символьные имена следующим образом, где LSB нумеруется как разрядный нуль:
Бит Имя Значение если установлено в #archive_options
0 have_special_formats archive_special_counts содержит количества
1 have_cp_numbers cp_number_counts содержит количества
2 have_all_code_flags code_flags_lo содержит элемент для каждого кода
3 have_cp_extra_counts cp_extra_counts содержит количества
4 have_file_headers archive_file_counts содержит количества
5 deflate_hint запросите сжатый файл JAR на все элементы
6 have_file_modtime file_modtime содержит modtimes
7 have_file_options file_options содержит биты опции
8 have_file_size_hi file_size_hi содержит слова размера старшего разряда
9 have_class_flags_hi class_flags_hi содержит дополнительные флаги атрибута
10 have_field_flags_hi field_flags_hi содержит дополнительные флаги атрибута
11 have_method_flags_hi method_flags_hi содержит дополнительные флаги атрибута
12 have_code_flags_hi code_flags_hi содержит дополнительные флаги атрибута
13   (неиспользованный, должен быть нуль),
...   (неиспользованный, должен быть нуль),
31   (неиспользованный, должен быть нуль),

Если have_special_formats (LSB) будет установлен, полоса, то у archive_special_counts будет два элемента, как определено в грамматике. Иначе у этой полосы будут нулевые элементы. Точно так же, если have_cp_numbers будет установлен, полоса, то у cp_number_counts будет четыре элемента, как определено в грамматике. Иначе у этой полосы будут нулевые элементы. Если have_all_code_flags устанавливается, полоса, code_flags должен содержать один элемент для каждого атрибута Code. Иначе у этой полосы может быть меньше элементов. (Эта опция полезна, когда атрибуты Code богаты податрибутами, возможно потому что JAR содержит большое количество отладочной информации.)

Если have_cp_extra_counts будет установлен, полоса, то cp_extra_counts будет содержать четыре элемента, как определено в грамматике. Иначе у этой полосы будут нулевые элементы. (Флаг может только быть установлен, когда #archive_majver 170 или выше. Эти дополнительные количества соответствуют дополнительным постоянным типам пула, представленным в недавних версиях формата classfile.)

Если have_file_headers будет установлен, полоса, то у archive_file_counts будет пять элементов, как определено в грамматике. Иначе у этой полосы будут нулевые элементы. Если deflate_hint устанавливается, декомпрессор требуют (но не требуется) уменьшать размер его вывода. Например, если это производит файл JAR, это может выкачать элементы JAR. Если опция have_file_modtime (или have_file_options, have_file_size_hi, have_class_flags_hi, have_field_flags_hi, have_method_flags_hi, have_code_flags_hi, соответственно) устанавливается, соответствующая полоса, file_modtime (или file_options, file_size_hi, class_flags_hi, field_flags_hi, method_flags_hi, code_flags_hi, соответственно) может быть непустым, как определено ниже. Иначе у той полосы будут нулевые элементы. Другие биты в опциях архива должны быть нулем и резервируются для будущего использования.

Сразу после того, как слово #archive_options является парой 32-разрядных чисел, которые вместе формируют 64-разрядную длину, которая помогает декомпрессорам легко буферизовать входящие данные до конца сегмента архива, не читая вне сегмента. Значение #archive_size является 64-разрядным значением без знака, составленным из 32-разрядных слов без знака #archive_size_lo и #archive_size_hi, где прежнее значение является младшим разрядом 32-разрядное слово и последнее значение, является старшим разрядом 32-разрядное слово. Значение #archive_size является или нулем или объявляет число байтов в сегменте архива, запускаясь сразу после #archive_size_lo и перед #archive_next_count и заканчиваясь последней полосой, полосой *file_bits. (Таким образом, ненулевой размер включает размер #archive_next_count, *file_bits, и всего промежуточный.) Это значение избыточно, но если ненулевой должно быть правильно предоставлено любым компрессором. Если сегмент архива передается как часть потока, и если другие данные (такие как дополнительные сегменты) следуют за архивом, значение #archive_size не должно быть нулем. Хотя это может быть полностью проигнорировано декомпрессором, это значение может помочь некоторым декомпрессорам буферизовать свои вводы более эффективно.

Сразу после того, как #archive_size является другим значением #archive_next_count, который оценивает число сегментов архива сразу после текущего. Это число не должно быть корректным, и может всегда быть нулем. Это предназначается, чтобы предоставить декомпрессорам подсказку как на сумму остающейся работы распаковки, чтобы сделать. (Такие подсказки обычно выводятся на экран в индикаторах выполнения.)

Если значение #archive_modtime является ненулевым, декомпрессор требуют (но не требуется) скорректировать специфичное для системы время изменения для его вывода. Например, если декомпрессор производит файл JAR, он может назначить дату модификации каждого элемента JAR, или файла JAR непосредственно, к той дате, в отсутствие больше определенного направляющий, такое ненулевое значение file_modtime. Значение #archive_modtime интерпретируется как число секунд начиная с эпохи, используемой System.currentTimeMillis, который является 01.01.1970, GMT 0:00:00. Однако, специальный нуль значения резервируется, чтобы указать на отсутствие любого времени изменения для архива в целом. Декомпрессор может предоставить произвольное значение вместо недостающего времени изменения архива. Если это делается, и если значения file_modtime присутствуют, те значения интерпретируются относительно времени изменения, предоставленного для #archive_modtime компрессором.

Значение #file_count дает число файлов, которые описываются подробно архивом. Отметьте, что файл class, который достаточно прост (столь же описанный ниже) не должен быть описан как файл, потому что это достаточно, что сам class передается. Поэтому, #file_count может быть меньше чем число переданных классов. (Это последнее число вызывают #class_count.) С другой стороны переданные файлы не должны содержать классы, так, чтобы #file_count мог также быть больше чем число классов.

5.2.2. Объект архива графы и Формат Класса

Архивный файл содержит до шестнадцати наборов констант, вызванных "постоянные пулы". (Эти структуры аналогичны, но не идентичны к так же именованной структуре в файлах class.) Эти постоянные пулы описываются подробно в следующем разделе.

Количество элементов каждого постоянного пула дается в формате UNSIGNED5 в элементах структуры cp_counts заголовка архива:

  cp_counts:
        #cp_Utf8_count :UNSIGNED5[1]
        (cp_number_counts) ** (#have_cp_numbers)
        #cp_String_count :UNSIGNED5[1]
        #cp_Class_count :UNSIGNED5[1]
        #cp_Signature_count :UNSIGNED5[1]
        #cp_Descr_count :UNSIGNED5[1]
        #cp_Field_count :UNSIGNED5[1]
        #cp_Method_count :UNSIGNED5[1]
        #cp_Imethod_count :UNSIGNED5[1]
        (cp_extra_counts) ** (#have_cp_extra_counts)

  cp_number_counts:
        #cp_Int_count :UNSIGNED5[1]
        #cp_Float_count :UNSIGNED5[1]
        #cp_Long_count :UNSIGNED5[1]
        #cp_Double_count :UNSIGNED5[1]

  cp_extra_counts:
        #cp_MethodHandle_count :UNSIGNED5[1]
        #cp_MethodType_count :UNSIGNED5[1]
        #cp_BootstrapMethod_count :UNSIGNED5[1]
        #cp_InvokeDynamic_count :UNSIGNED5[1]

  archive_special_counts:
        #band_headers_size :UNSIGNED5[1]
        #attr_definition_count :UNSIGNED5[1]

  class_counts:
        #ic_count :UNSIGNED5[1]
        #default_class_minver :UNSIGNED5[1]
        #default_class_majver :UNSIGNED5[1]
        #class_count :UNSIGNED5[1]

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

Четыре числовых постоянных пула измеряются cp_number_counts. Они определяют числа, используемые иногда байт-кодами ldc. Поскольку меньшинство классов фактически использует такие байт-коды, размеры являются дополнительными под управлением #have_cp_numbers.

Аналогично, последние четыре постоянных пула измеряются cp_extra_counts. Они определяют информацию о редактировании для инструкции invokedynamic, и определенные типы констант (дескрипторы метода и типы метода). Как с числовыми записями, эти размеры являются дополнительными под управлением #have_cp_extra_counts.

У каждого файла class есть заголовок, который включает магическое число и номера вспомогательной версии и номера основной версии. Магическое число (0xCAFEBABE), будучи фиксированной постоянной, не передается в архиве Pack200. Однако, номера версий, которые могут измениться несколько, должны быть записаны.

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

Отдельные классы в архиве (как отмечено ниже) могут дополнительно определить свои собственные номера версий в псевдоатрибуте, который переопределяет #default_class_minver и #default_class_majver, данный в заголовке архива.

Количество #band_headers_size дает размер в байтах band_headers. Формат этих байтов, какая справка определяет спецификаторы кодирования полосы для вторичного codings, будет обсужден намного позже в разделе по метакодированию.

Заголовок архива также определяет, что число (#attr_definition_count) типов атрибута, определения class (#class_count), вкладывало объявления class (#ic_count). Эти числа используются, чтобы измерить различные другие полосы, как отмечено в определении тех полос.

Арифметическая сумма всех чисел в cp_counts должна быть меньше чем значение 536870912 (2^29). Компрессору запрещают передать архив, для которого сумма достигает или превышает этот предел. Это ограничение предназначается, чтобы позволить декомпрессорам использовать, внутренне, объединенную нумерацию констант, даже если определенные константы (такие как demangled внутренние имена class или неявные имена SourceFile) должны быть добавлены на лету во время распаковки к постоянному пулу.

Примечание по реализации: archive_header непосредственно содержит 3 числа, в то время как cp_counts содержит по крайней мере 8 чисел, и class_counts содержит точно 4. Поэтому, минимальный размер archive_header составляет 15 байтов, и этому всегда предшествуют на 4 байта archive_magic. Декомпрессор, который хотел избежать любого побочное чтение вперед, мог считать и буферизовать начальный блок 19 байтов, которые будут уверенны, что содержали поля #archive_size. (Это предполагает, что номера версий являются небольшими, как они.) Это могло тогда сразу проанализировать достаточную информацию, чтобы определить, сколько дополнительных байтов буферного накопителя будет обязано сканировать остальную часть архива, по крайней мере до изображений файла ресурсов. К тому времени, когда изображения файла ресурсов в *file_bits должны быть проанализированы, декомпрессор уже считает полосы *file_size, и будет в состоянии удалить любую неопределенность, первоначально существующую в #archive_size. (Если поля #archive_size являются нулем, декомпрессор может быть вынужден читать вслепую до конца всех данных на входном канале, чтобы проанализировать архив.)

5.3. Постоянные Пулы

Формат определяет шестнадцать независимых постоянных пулов, одиннадцать из которых соответствуют непосредственно одиннадцати основным типам констант, найденных в Java файлы class. В формате архива Pack200 они организуются в фиксированном логическом упорядочивании, названном их порядком определения. Этот порядок определяет их представление в структуре полосы архива, и также конструкцию определенного постоянного numberings.

Постоянные пулы консолидируют информацию в постоянных пулах всего ввода файлы class. Каждый постоянный пул содержит единственный тип постоянной величины. Каждый из одиннадцати постоянных типов пула, найденных в Java 6 файлов class, помещается в его собственный постоянный пул. Двенадцатый пул содержит подписи, которые в файлах class являются строками UTF8, которые представляют метод, и типы поля, но в архивах Pack200 являются отдельно сжатым типом данных.

Еще три постоянных пула содержат константы, определенные как часть Java 7 форматов classfile (основная версия 51 или позже). Еще один постоянный пул содержит константы, которые будут собраны в атрибут BootstrapMethods, который может быть просмотрен как приложение к classfile постоянному пулу.

Следующая таблица дает шестнадцать предопределенных постоянных пулов в их порядке определения. Это также определяет их корреспонденцию постоянным типам, найденным в Java формат файла class.

Имя Элемент файла class Тег файла class Цель
cp_Utf8 CONSTANT_Utf8_info CONSTANT_Utf8 основные строковые данные
cp_Int CONSTANT_Integer_info CONSTANT_Integer международная константа
cp_Float CONSTANT_Float_info CONSTANT_Float константа плавающая
cp_Long CONSTANT_Long_info CONSTANT_Long долго постоянный
cp_Double CONSTANT_Double_info CONSTANT_Double двойная константа
cp_String CONSTANT_String_info CONSTANT_String Строковая константа
cp_Class CONSTANT_Class_info CONSTANT_Class Ссылка class
cp_Signature (см. ниже), (ни один) метод, поле, или тип переменной
cp_Descr CONSTANT_NameAndType_info CONSTANT_NameAndType пара (имя, введите),
cp_Field CONSTANT_Fieldref_info CONSTANT_Fieldref полевая ссылка
cp_Method CONSTANT_Methodref_info CONSTANT_Methodref вызов метода
cp_Imethod CONSTANT_InterfaceMethodref_info CONSTANT_InterfaceMethodref вызов интерфейса
cp_MethodHandle CONSTANT_MethodHandle_info CONSTANT_MethodHandle постоянный дескриптор метода
cp_MethodType CONSTANT_MethodType_info CONSTANT_MethodType постоянный тип метода
cp_BootstrapMethod BootstrapMethods_attribute.bootstrap_methods [я] (ни один; приставной стол к постоянному пулу) спецификатор метода начальной загрузки
cp_InvokeDynamic CONSTANT_InvokeDynamic_info CONSTANT_InvokeDynamic вызов invokedynamic

(Отметьте, что порядок определения на эти постоянные пулы подобен числовому упорядочиванию соответствующего тега файла class. Например, CONSTANT_Utf8 является первым тегом, и cp_Utf8 является первым постоянным пулом в порядке определения. Однако, подробно есть различия. В частности отметьте, что cp_String прибывает прежде cp_Class, даже при том, что соответствующие теги файла class находятся в обратном порядке.)

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

В отличие от формата файла class, постоянная индексация пула в формате архива Pack200 запускается в нуле. В редких местах, где нулевые ссылки ожидаются, документируется возможность, и сами нулевые ссылки кодируются нулем, индексируют, в то время как все другой индексировать значения постепенно увеличиваются одним. Где нулевые ссылки не ожидаются, они могут все еще быть закодированы 32-разрядным, индексируют значение-1.

Также в отличие от файлов class, нет никаких "разрывов", или неиспользованный индексирует связанный с длинными или двойными значениями. Иногда, мы обратимся формально к элементу постоянного пула при использовании нотации массива. Например, первыми тремя целыми числами в cp_Int, постоянным пулом является cp_Int[0], cp_Int[1], и cp_Int[2], и последнее целое число, является cp_Int[cp_Int_count-1]. Отметьте, что обе полосы и постоянные пулы обрабатываются в этой спецификации как массивы с нулевым источником.

Это недопустимо для компрессора, чтобы передать ту же самую константу дважды. Таким образом, все постоянные записи пула должны быть уникальными.

В файле class, за немногим исключением, постоянные ссылки пула со строгим контролем типов, в той каждой ссылке или нуль или обращается к постоянной записи пула фиксированного тега, связанного с контекстом ссылки. Исключения являются атрибутами ConstantValue и полями операнда ldc, ldc_w, и инструкций ldc2_w.

Однако, потому что постоянные пулы в архиве Pack200 отдельно индексируются, все постоянные ссылки должны быть со строгим контролем типов, так, чтобы был только один постоянный пул (или подмножество пула), в который любой данный индексирует, применяется. Это выполняется любой, выводя постоянный тип из контекста (в случае атрибутов ConstantValue) или добавляя дополнительную информацию к контексту ссылки. (В потоке байт-кода ldc разделяется постоянным типом в отличные инструкции sldc, ildc, и т.д.),

Расположение постоянных полос пула в архиве следует за порядком определения постоянных пулов непосредственно. Каждый постоянный пул представляется в свою очередь последовательностью одной или более полос. Последовательность постоянных полос пула поэтому структурируется следующим образом:

  cp_bands:
        cp_Utf8
        *cp_Int :UDELTA5 [#cp_Int_count]
        *cp_Float :UDELTA5 [#cp_Float_count]
        cp_Long
        cp_Double
        *cp_String :UDELTA5 [#cp_String_count] (cp_Utf8)
        *cp_Class :UDELTA5 [#cp_Class_count] (cp_Utf8)
        cp_Signature
        cp_Descr
        cp_Field
        cp_Method
        cp_Imethod
        cp_MethodHandle
        *cp_MethodType :UDELTA5 [#cp_MethodType_count] (cp_Signature)
        cp_BootstrapMethod
        cp_InvokeDynamic

Как может быть замечен здесь, постоянные пулы, записи которых могут быть получены из единственного 32-разрядного целого числа или единственной ссылки, представляются как единственные полосы. Другие постоянные пулы представляются как группы полос. Каждый постоянный пул дает свое имя к соответствующему элементу грамматики. Производство cp_bands объявляет порядок каждой полосы или группу полос, которая передает константы в eponymous постоянном пуле.

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

В нескольких случаях несколько из шестнадцати постоянных пулов объединяются в группу, так, чтобы индексировал, может быть сформирован, чтобы обратиться к элементам группы в целом. Такая группа полностью определяется ее составляющими постоянными пулами. Индексирование в постоянную группу пула всегда последовательно формируется с полным порядком составляющих постоянных пулов, так же как с внутренним порядком каждого пула. Например, если группа, cp_ABC формируется из трех пулов cp_A, cp_B, и cp_C размеров COUNT(cp_A), COUNT(cp_B), и COUNT(cp_C), соответственно, то группа индексирует, выбирает из одного из трех пулов в зависимости от того, является ли это в диапазоне 0 .. COUNT(cp_A)-1, COUNT(cp_A) .. COUNT(cp_A)+COUNT(cp_B)-1, или COUNT(cp_A)+COUNT(cp_B) .. COUNT(cp_ABC)-1, соответственно. Размер группы пула является, конечно, суммой составляющих пулов.

В некоторых других случаях подмножества постоянных пулов индексируются сокращенным способом. Индексирование в постоянное подмножество пула всегда последовательно формируется с порядком пула непосредственно. Например, индексировать 0 всегда обращается к первому элементу подмножества, индексировать 1 обращается к второму и так далее.

Вот определения групп пула, используемых в этой спецификации.

Имя Составляющие Цель
cp_All (все шестнадцать пулов) универсальные ссылки
cp_LoadableValue cp_Int, cp_Float, cp_Long, cp_Double, cp_String, cp_Class, cp_MethodHandle, cp_MethodType Операнд qldc, параметр метода начальной загрузки
cp_AnyMember cp_Field, cp_Method, cp_Imethod get или операнд invoke, компонент дескриптора метода
Группа cp_All включает последовательность всех констант в их естественном порядке возникновения в пределах архива Pack200. Таким образом индексирование в cp_All является в действительности нетипизированной ссылкой на любую константу.
5.3.1. Скалярные Константы
Кодирование cp_Utf8 постоянный пул будет описано коротко. Сначала мы опишем кодирование числового, строки, и class постоянные пулы.

Значения в cp_Int постоянный пул непосредственно представляются значениями, закодированными в его полосе. Значения в cp_Float постоянный пул получаются как будто, применяя java.lang.Float.intBitsToFloat к 32-разрядным значениям, закодированным в его полосе.

64-разрядные значения полосы cp_Long получаются, примыкая, как высокие и низкие слова, соответствующие 32-разрядные значения от этих двух полос cp_Long_hi и cp_Long_lo. (Они содержат высокие и низкие слова, соответственно.) Аналогично, значения полосы cp_Double получаются первыми смежными высокими и низкими словами из двух других полос, и затем перепечатыванием получающихся 64-разрядных целых чисел как будто, применяя java.lang.Double.longBitsToDouble. Высокие и низкие слова находятся в полосах cp_Double_hi и cp_Double_lo, соответственно.

  cp_Long:
        *cp_Long_hi :UDELTA5 [#cp_Long_count]
        *cp_Long_lo :DELTA5 [#cp_Long_count]

  cp_Double:
        *cp_Double_hi :UDELTA5 [#cp_Double_count]
        *cp_Double_lo :DELTA5 [#cp_Double_count]
 

Когда значения с плавающей точкой в конечном счете пишутся файлам class, их биты должны быть точно сохранены, как будто они были обработаны java.lang.Float.floatToRawIntBits или java.lang.Double.doubleToRawLongBits. Таким образом значения "НЭН" передаются искренне без нормализации.

(Отметьте: Хотя было бы возможно расширить кодирующие полосу методы Pack200, чтобы закодировать 64-разрядные значения непосредственно, этот формат файла всегда передает 64-разрядные значения как пар 32-разрядных значений, переданных в парах полос. Это упрощает реализации, позволяя им обработать данные полосы с 32-разрядными информационными каналами.)

Каждая строка в cp_String постоянный пул представляется в его полосе ссылкой на написание строки как постоянный cp_Utf8.

Аналогично, каждый class в cp_Class постоянный пул представляется в его полосе ссылкой на написание class как постоянный cp_Utf8. (Как в файле class и VM, написание использует символ наклонной черты, чтобы разграничить компоненты префикса пакета.)

5.3.2. Константы Utf8
Каждое значение в cp_Utf8 постоянный пул является массивом нуля или большего количества 16-разрядных символов Java. (Имя "Utf8" является анахронизмом, обращаясь только к основной символьной строке вводит Java файлы class. Никакая часть формата файла Pack200 не использует кодирования UTF, но термин "Utf8" сохраняется, чтобы подчеркнуть соединение с файлами class.) Как в формате файла class, все данные символьной строки передаются в этом виде постоянной записи пула. Когда контекст является достаточно четким, мы свободно именуем эти массивы как "строки", даже при том, что они отличны от констант Java в cp_String постоянном пуле.

Если cp_Utf8 не пуст, его первое значение всегда является пустой строкой. Таким образом пустой строке всегда дают индексирование нуля. Никакие значения полосы не передаются, чтобы представить эту пустую строку. (Значения в полосах cp_Utf8_prefix и cp_Utf8_suffix принадлежат строкам после пустой строки в cp_Utf8.), Поскольку константы не могут быть дублированы, все другие элементы cp_Utf8 содержат по крайней мере один символ.

Каждая строка в cp_Utf8 постоянный пул представляется в архивном файле в двух частях, префиксе и суффиксе. Суффикс представляется и количеством и последовательностью символьных кодов. Префикс представляется только количеством; символы префикса дублируются от предыдущей строки. Этот метод позволяет компрессор (если это выбирает) представлять строки посредством их последовательных различий. Первое суффиксное значение и первые два префиксных значения подавляются в переданном архиве. Значения, если передано, всегда были бы нулем, так как первая строка cp_Utf8 всегда пуста, и вторая строка никогда не может совместно использовать непустой префикс с первой строкой.

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

  cp_Utf8:
        *cp_Utf8_prefix :DELTA5      [MAX(0,#cp_Utf8_count-2)]
        *cp_Utf8_suffix :UNSIGNED5   [MAX(0,#cp_Utf8_count-1)]
        *cp_Utf8_chars :CHAR3        [SUM( *cp_Utf8_suffix )]
        *cp_Utf8_big_suffix :DELTA5  [COUNT(0, *cp_Utf8_suffix )]
        (*cp_Utf8_big_chars :DELTA5)
          ** length(cp_Utf8_big_suffix)  [SUM( *cp_Utf8_big_suffix )]
 
(Отметьте: Это полезно, но не требуемое этой спецификацией, чтобы упорядочить строки лексикографически и найти максимальные общие префиксы между смежными строками. Допустимо проигнорировать функцию совместного использования префикса и объявить, что все префиксы нуль.)

Полоса cp_Utf8_suffix содержит меньше чем элементы #cp_Utf8_count. Это определяет, в порядке, маленькой суффиксной длине каждой постоянной строки пула (кроме неявной первой строки, которая пуста). Полоса cp_Utf8_prefix содержит два меньше чем элементы #cp_Utf8_count. Это определяет, в порядке, длине префикса каждой постоянной строки пула (кроме первых двух строк, у которых всегда есть нулевые длины префикса). Длина префикса кодирует длину префиксной подстроки, совместно использованной и cp_Utf8[i-1] и cp_Utf8[i]. Если есть меньше чем три строки в cp_Utf8, то cp_Utf8_prefix пуст. Длина префикса обычно является значительной долей (иногда половина) полной длины.

Каждое значение в полосе cp_Utf8_chars является 16-разрядным числом, выражающим символ Java. Эта полоса содержит символы всех маленьких суффиксов в порядке. Для каждой последовательной строки cp_Utf8_chars содержит дополнительное выполнение значений, кодирующих символы его маленького суффикса, если любой. Поэтому, полная длина этой полосы является суммой всех значений в полосе cp_Utf8_suffix.

Всякий раз, когда маленькая суффиксная длина для постоянной записи пула является нулем, у строки нет никакого маленького суффикса, но большого суффикса вместо этого. Длина каждого большого суффикса дается элементом полосы cp_Utf8_big_suffix. (Поэтому, длина этой полосы является точно количеством нулевых значений в полосе cp_Utf8_suffix.) Каждый большой суффикс передается как отдельная полоса 16-разрядных символьных значений, один элемент полосы на символ. Есть одна такая полоса на большой суффикс. Эти полосы сразу следуют за полосой cp_Utf8_big_suffix, и все вместе вызываются полосами cp_Utf8_big_chars. Хотя обычно данные того же самого типа собираются в единственную полосу, эти строки помещаются в отдельные полосы так, чтобы они могли быть независимо закодированы. Эти строки обычно кодируют массивы двоичных данных, а не истинные символы Java.

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

Пожалуйста, см. раздел Приложения для псевдокода, объясняя это понятие.

5.3.3. Введите Подписи
Каждый cp_Signature постоянная запись пула представляет строку типа, точно как поле и типы метода, объявляется в формате файла class. Хотя формат файла class использует простой Utf8 постоянные записи пула для таких строк, формат файла Pack200 выделяет отдельный постоянный пул для них, чтобы использовать более компактное представление чем для общих строк.

Константы подписи являются особенными в этом, они могут содержать встроенные ссылки на константы cp_Class. Постоянная подпись эквивалентна константе Utf8, как только встроенные ссылки class расширяются в их написания. Константы подписи достаточно гибки, чтобы представить произвольные строки, но предназначаются для строк, которые часто содержат имена class после эля прописной буквы 'L'. Они включают поле, метод, и типы локальных переменных, и универсальные атрибуты Signature.

Каждая строка подписи анализируется в форму и последовательность нуля или большего количества ссылок class. Ссылки class получаются, располагаясь в исходной строке подписи все последовательности, которые соответствуют образец "имя класса L", удаляя часть имени класса, и обрабатывая ее как ссылка в cp_Class постоянный пул. Форма определяется как остаток после того, как имена class были удалены из исходной строки.

Форме не позволяют содержать возникновения эля буквы ('L') кроме тех, которые отмечают удаленные имена class.

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

Отметьте, что константы cp_Class не обязаны обращаться к существующим классам, и при этом они даже не требуются иметь допустимые написания имени class. Поэтому, у компрессора есть значительная широта в выборе, который называет class (если любой), это извлечет из строк подписи. В крайнем случае компрессор может сделать каждую форму идентичной ее соответствующей строке подписи, и просто удовлетворить ее длину class, испуская ссылки на фиктивный class с пустым названием. (Эта длина class должна была бы включать любые возникновения 'L' на имена class непосредственно.)

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

Правила также позволяют компрессору решать, произвольно, сколько символов (если кто-либо) после каждого эля буквы 'L' будет передан как часть имени class. Поэтому, данная строка подписи может быть представимой несколькими формами, любая из которых декомпрессор должен быть подготовлен обработать.

Вот некоторые примеры:

Введите Строку Подписи Форма Класс
Лен.
Класс...
F F 0  
[Z [Z 0  
[[[LLL; [[[L; 1 LL
[[[LLL; [[[LLL; 3 (empty), (empty), (empty)
([Ljava/lang/String;)V ([L;)V 1 java/lang/String
Ljava/util/List<Lpkg/Item;>; L<L;>; 2 java/util/List, pkg/Item
(Ljava/lang/String;II)Lpkg/Item; (L;II)L; 2 java/lang/String, pkg/Item
Ljava/util/List<Ljava/lang/Byte;>; L<L;>; 2 java/util/List, java/lang/Byte
<ELEM:>(Ljava/util/List<TELEM;>;)TELEM; <EL:>(L<TEL;>;)TEL; 1 EM, java/util/List, EM, EM
ALLOWABLE ALLOWABLE 3 (empty), (empty), (empty)
ALLOWABLE AL 1 LOWABLE
ALLOWABLE ALABL 2 LOW, E

Формы всех строк в cp_Signature постоянный пул даются в порядке в полосе cp_Signature_form как одна ссылка cp_Utf8 на строку подписи. Для каждой формы class последовательность длиной классов, требуемых воссоздавать строку подписи, передается как выполнение ссылок cp_Class в полосе cp_Signature_classes. Как следствие этих определений длина полосы cp_Signature_classes является общим количеством эля буквы возникновения 'L' в последовательности написаний форм, упомянутых в cp_Signature_form.

  cp_Signature:
        *cp_Signature_form :DELTA5 [#cp_Signature_count](cp_Utf8)
        *cp_Signature_classes :UDELTA5 [COUNT('L',...)] (cp_Class)
 

Пожалуйста, см. раздел Приложения для псевдокода, объясняя это понятие.

5.3.4. Константы кортежа
Следующие четыре постоянных пула содержат упорядоченные пары различных видов значений (типы, имена, строки, или классы). Каждый постоянный cp_Descr является упорядоченной парой имени (представленный как ссылка cp_Utf8) и тип (представленный как ссылка cp_Signature). Эти ссылки передаются в соответствующих элементах полосах cp_Descr_type и cp_Descr_name.

Аналогично, каждый cp_Field, cp_Method, или постоянный cp_Imethod являются упорядоченной парой class (представленный как ссылка cp_Class) и дескриптор имени-и-типа (представленный как ссылка cp_Descr). Снова, эти ссылки передаются в соответствующих элементах связанных полос.

  cp_Descr:
        *cp_Descr_name :DELTA5 [#cp_Descr_count] (cp_Utf8)
        *cp_Descr_type :UDELTA5 [#cp_Descr_count] (cp_Signature)
  cp_Field:
        *cp_Field_class :DELTA5 [#cp_Field_count] (cp_Class)
        *cp_Field_desc :UDELTA5 [#cp_Field_count] (cp_Descr)
  cp_Method:
        *cp_Method_class :DELTA5 [#cp_Method_count] (cp_Class)
        *cp_Method_desc :UDELTA5 [#cp_Method_count] (cp_Descr)
  cp_Imethod:
        *cp_Imethod_class :DELTA5 [#cp_Imethod_count] (cp_Class)
        *cp_Imethod_desc :UDELTA5 [#cp_Imethod_count] (cp_Descr)
 
5.3.5. Дополнительные Константы
Поскольку дополнительные постоянные пулы определяют символьные ссылки для инструкций invokedynamic и связанных объектов. (Эти постоянные пулы только непусты, если их соответствующие количества являются ненулевыми, который поочередно может только быть истиной, если cp_extra_counts присутствует.) Каждый cp_MethodHandle является упорядоченной парой ссылочного вида (маленькое целое число) и ссылка на элемент cp_Field, cp_Method, или cp_Imethod. (Эта ссылка передается как индексирование в cp_AnyMember, который определяется выше как группа пула, содержащая те три пула.) Каждый cp_MethodType представляется как ссылка cp_Signature. Каждый cp_InvokeDynamic является упорядоченной парой спецификатора метода начальной загрузки (представленный как cp_BootstrapMethod) и тип (представленный как ссылка cp_Signature). Каждый спецификатор cp_BootstrapMethod является упорядоченной парой ссылки метода начальной загрузки (представленный как cp_MethodHandle) и считаемая серия нуля или большего количества постоянных ссылок пула на константы, которые могут быть загружены на стек JVM. (Эти ссылки передаются, как индексирует в группу пула cp_LoadableValue.) Все эти значения и ссылки передаются в связанных полосах как описано ниже.
  cp_MethodHandle:
        *cp_MethodHandle_refkind :DELTA5 [#cp_MethodHandle_count]
        *cp_MethodHandle_member :UDELTA5 [#cp_MethodHandle_count] (cp_AnyMember)
  cp_BootstrapMethod:
        *cp_BootstrapMethod_ref :DELTA5 [#cp_BootstrapMethod_count] (cp_MethodHandle)
        *cp_BootstrapMethod_arg_count :UDELTA5 [#cp_BootstrapMethod_count]
        *cp_BootstrapMethod_arg :DELTA5 [SUM(*BootstrapMethod_arg_count)] (cp_LoadableValue)
  cp_InvokeDynamic:
        *cp_InvokeDynamic_spec :DELTA5 [#cp_InvokeDynamic_count] (cp_BootstrapMethod)
        *cp_InvokeDynamic_descr :UDELTA5 [#cp_InvokeDynamic_count] (cp_Descr)

5.4. Атрибуты файла

Так как архив JAR состоит из последовательности файлов, каждого с содержанием и несколькими другими атрибутами, архив Pack200 может также представить последовательность файлов с их атрибутами. Конечно, содержание файлов class особенно передается, но содержит ли файл (то есть, элемент архива JAR) class или другой ресурс, архив Pack200 в состоянии передать следующие атрибуты:

Файл class, содержание которого сжимается Pack200, отмечается как "тупик" со специальным битом опции. У файла тупика class, как должны объявлять, есть длина нуля. У этого, как могут объявлять, есть пустая строка для ее имени. Если есть недостаточно многие файлы тупика class, переданные, чтобы соответствовать с числом переданных классов, декомпрессор должен действовать, как будто компрессор передал дополнительную серию тривиальных тупиков без имени или содержания, и время изменения и подсказка дефляции, скопированная с заголовка архива.

Каждый файл ресурсов передается в архиве Pack200 как простое изображение bytewise под относительным путем, используя наклонную черту '/' как разделитель каталога. (Это - то же самое соглашение пути, как используется в архивах ZIP.) Каждый файл (оба файла ресурсов и файлы class) может дополнительно быть связан с подсказкой дефляции и датой модификации.

  file_bands:
        *file_name :UNSIGNED5 [#file_count] (cp_Utf8)
        *file_size_hi :UNSIGNED5 [#file_count*(#have_file_size_hi)]
        *file_size_lo :UNSIGNED5 [#file_count]
        *file_modtime :DELTA5 [#file_count*(#have_file_modtime)]
        *file_options :UNSIGNED5 [#file_count*(#have_file_options)]
        *file_bits :BYTE1 [SUM(*file_size)]
 

Нет никаких дополнительных атрибутов файла, таких как комментарии, дополнительные атрибуты, или значения CRC. Приложение, которое требует таких атрибутов на некоторых файлах, может закодировать те файлы в соответствующий формат архивного файла (такие как ZIP), и передать те архивы как файлы ресурсов в архиве Pack200.

Каждое имя файла передается как элемент полосы file_name, и каждая длина (в байтах) передается в соответствующих элементах полосы file_size_lo и (если есть) полосы file_size_hi. Все три полосы имеют длину #file_count, за исключением того, что у file_size_hi есть нулевые элементы, если бит have_file_size_hi в #archive_options является четким.

Длина в байтах каждого файла является соответствующим 32-разрядным значением без знака, принятым от полосы file_size_lo, если полоса file_size_hi пуста. Иначе, длина файла является 64-разрядным значением без знака, составленным из corresonding 32-разрядных элементов без знака file_size_lo и полос file_size_hi, где прежнее значение является младшим разрядом, 32-разрядное слово и последнее значение являются старшим разрядом 32-разрядное слово.

Байты всего non-class (то есть, ресурс) файлы сразу следуют в полосе file_bits. Каждый файл дается как соответствующее выполнение значений байта.

Дополнительная полоса file_modtime, если не пустой, предоставляет время изменения для каждого файла ресурсов (и потенциально для файлов class, если тупики файла class присутствуют). Каждое целочисленное значение дает различие (в секундах) от значения #archive_modtime. (Поэтому, если значение #archive_modtime является нулем, отдельные времена файла должны быть интерпретированы как абсолютные значения.) Порядок передачи file_modtime является непротиворечивым с file_name. Эта полоса пуста, если бит have_file_modtime в #archive_options является четким.

Дополнительная полоса file_options, если не пустой, предоставляет флаговые биты для каждого файла ресурсов (и потенциально для файлов class, если тупики файла class присутствуют). Эта полоса пуста, если бит have_file_options в #archive_options является четким. Каждое слово file_options интерпретируется поразрядное. Определенным битам дают символьные имена следующим образом, где LSB нумеруется как разрядный нуль:

Бит Имя Цель
0 deflate_hint запросите сжатый элемент файла JAR
1 is_class_stub этот файл содержит байт-коды class

Если deflate_hint (LSB) устанавливается, декомпрессор требуют (но не требуется) уменьшать размер его вывода. Например, если это производит файл JAR, это может выкачать элементы JAR. Так как бит deflate_hint в слове #archive_options имеет тот же самый эффект, два бита в действительности объединяются с логическим ИЛИ для каждого файла. Если is_class_stub (второй LSB) устанавливается, это описание файла ресурсов является фактически тупиком, и содержание файла определяется как байт-коды одного из классов, определенных в архиве Pack200. Другие биты в опциях файла должны быть нулем и резервируются для будущего использования.

Если переданный файл отмечается как тупик class, его содержание должно быть передано, как будто файл был пуст. (Таким образом, file_size_hi и file_size_lo должны и быть нулем, и в file_bits, возможно, нет никаких соответствующих байтов.) Декомпрессор обязан предоставлять содержание для файла ресурсов, воссоздавая содержание файла class для class, переданного в class_this и т.д. Как любой другой файл ресурсов, тупику class позволяют иметь имя, время изменения и deflate_hint.

Тупики class и классы соответствуют в порядке. Определите полученный параметр #class_stub_count как число файлов, отмеченных как тупики class. (Это - также количество набора битов is_class_stub в file_options.) Затем #class_stub_count должен быть не больше чем #class_count. Первый тупик class определяет файл, который получает байт-коды для первого class и так далее. Хотя у тупика class есть имя (переданный в file_name), это имя может быть пустой строкой. В этом случае декомпрессор обязан использовать стандартное имя для файла class, который создается из имени байт-кода class (использующий наклонную черту '/' для разделителя пакета), добавляя строку ".class". (Таким образом у classfile может быть произвольное нестандартное имя, но работы сжатия лучше всего, если его имя получается из его class обычным способом.)

Если #class_count больше чем #class_stub_count, то декомпрессор должен вести себя, как будто достаточное число тривиальных дополнительных тупиков class было передано после последнего явного файла. У этих тривиальных тупиков есть строка пустого названия и нулевой deflate_hint или file_modtime.

Таким образом, в простом случае, где нет никаких тупиков class вообще (возможно, потому что have_file_options является нулем), декомпрессор должен произвести свои файлы в их порядке передачи, сопровождаемом порядком передачи классов. У каждого файла class должно быть свое стандартное имя, и время изменения и подсказка дефляции, наследованная от #archive_modtime и бита deflate_hint в #archive_options. Но за счет дополнительного размера передачи, компрессор может направить декомпрессор, чтобы представить ресурсы и файлы class в любом фиксированном порядке, с произвольными именами, время изменения, и подсказки дефляции для каждого выходного файла. Декомпрессор должен соблюдать это упорядочивание, если его вывод находится в форме (такой как архив JAR), где порядок является существенным.

Компрессоры свободны, если иначе не направлено, выбрать любое упорядочивание файлов. Часто выгодно поместить файлы с подобной статистикой друг рядом с другом, так, чтобы компрессор постпередачи (если кто-либо) мог обработать их содержание вместе (в том же самом окне, в случае ВЫКАЧИВАТЬ алгоритма). Вероятно, что у компрессора, который в состоянии переупорядочить его входные файлы для эффективной передачи, будет опция команды, которая вынуждает это сохранить порядок, в котором были представлены входные файлы, потому что этот порядок является существенным некоторым (но не все) приложения развертывания.

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

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

5.5. Флаги и Атрибуты

Формат файла Pack200 непосредственно поддерживает до 16 битов модификатора во всех выходных полях флагов, как определено форматом файла class. Это также непосредственно поддерживает определенные предопределенные атрибуты, такие как Code, InnerClasses, и ConstantValue, для компрессора также возможно определить дополнительные атрибуты, передавая достаточную информацию к декомпрессору, чтобы должным образом извлечь их данные из полос и воссоздать их в файлах class. Присутствием или отсутствием всех атрибутов управляет установка определенных битов в полосах флага.

Пять наборов полос флага переносят биты модификатора и/или приписывают биты управления. Полоса ic_flags переносит биты модификатора для вложенных классов. Кроме того, модификатор и биты управления атрибута переносят class_flags_lo, field_flags_lo, method_flags_lo, и code_flags_lo, и четыре соответствующих дополнительных высоких полосы слова, class_flags_hi, field_flags_hi, method_flags_hi, и code_flags_hi. (Нет никакого высокого слова для ic_flags.) Каждое значение в этих полосах интерпретируется как 32-разрядное двоичное число без знака. Каждый бит в этих полосах независимо определяет присутствие модификатора доступа Java (такого как ACC_PRIVATE), или class, поля, метода, или атрибута кода (такого как Deprecated или SourceFile), или некоторой другой необходимой управляющей информации (такой как, есть ли у файла class номер версии не по умолчанию).

У каждого class (resp. поле, метод, атрибут Code) есть соответствующее значение флагов до 63 битов, переданных в class_flags_lo (resp., field_flags_lo, method_flags_lo, code_flags_lo) и дополнительно в class_flags_hi (resp., field_flags_hi, method_flags_hi, code_flags_hi). Эти значения флагов, собранные в 64-разрядные числа, называют class_flags (resp., field_flags, method_flags, code_flags). За исключением атрибутов Code, каждый из низких шестнадцати флаговых битов может использоваться, чтобы передать флаги доступа. Высокие шестнадцать битов (или сорок семь, если дополнительное высокое слово передается) используются, чтобы указать на присутствие атрибутов, или предопределенных или определенных с помощью компрессора. Шестьдесят четвертая позиция двоичного разряда значения флагов (если передано) резервируется и должна быть нулем.

Значение флагов для атрибута Code является дополнительным и взято, чтобы быть нулем, отсутствуя. У атрибута Code есть соответствующее значение флагов, переданное, если и только если или бит have_all_code_flags в #archive_options устанавливается, или иначе у элемента code_headers, соответствующего атрибуту Code, есть специальный нуль значения. (См. обсуждение заголовков кода ниже.)

Для классов, вложенных классов, полей, и методов, присвоение позиций флагового бита к модификаторам является тем же самым как этим в формате файла class. (Например, LSB всегда представляет ACC_PUBLIC, и в архиве Pack200 и в форматах файлов class.) Атрибут переполнения является атрибутом, присутствие которого не обозначается непосредственно через флаговый бит, и но вместо этого обозначается возникновением индексировать в отдельной полосе. Для классов, полей, методов, и кодов, бит 16 (как установлено в маске 0x0001000) указывает на присутствие атрибутов переполнения. Для вложенных классов флаговый бит 16 указывает на присутствие явного внешнего class и полей имени, как объяснено ниже.

Бит Значение
0 ACC_PUBLIC
1 ACC_PRIVATE
2 ACC_PROTECTED
3 ACC_STATIC
4 ACC_FINAL
5 ACC_SYNCHRONIZED (ACC_SUPER)
6 ACC_VOLATILE (ACC_BRIDGE *)
7 ACC_TRANSIENT (ACC_VARARGS *)
8 ACC_NATIVE
9 ACC_INTERFACE
10 ACC_ABSTRACT
11 ACC_STRICT
12 ACC_SYNTHETIC*
13 ACC_ANNOTATION*
14 ACC_ENUM*
16 переполнение (больше данных полосы в другом месте)

Модификаторы, отмеченные со звездой (*), в новинку для недавних версий Java. Они присутствуют здесь для информации только, и не являются частью спецификации Pack200.

5.5.1. Присвоение Флаговых битов к Атрибутам
Присвоение позиций флагового бита к атрибутам делается в опции компрессора, и независимо определяется компрессором для четырех видов слов флага, которые имеют отношение к переносящим атрибут объектам (в классах, полях, методах, и кодах). Когда позиция флагового бита присваивается атрибуту, если тот бит видим в файле class, это должно быть вызвано четкое прежде, чем декомпрессор запишет это в файл class. Поэтому, если компрессор ожидает, что декомпрессор воспроизведет определенный ненулевой флаговый бит как выходной, компрессор должен воздержаться от присвоения той позиции двоичного разряда к атрибутам.

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

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

Любая из этих 63 позиций двоичного разряда в значении флагов может быть присвоена компрессором указать к декомпрессору на присутствие некоторого определенного атрибута. Компрессор может "принять" бит модификатора, присваивая это определение атрибута. (Это делается, испуская определение для атрибута, который упоминает ту позицию двоичного разряда.)

Если компрессор "вступает во владение" немного (модификатор или не), который используется по умолчанию в другой цели, бит теряет свое предыдущее значение. Однако, компрессор, возможно, не испускает явное определение для того же самого бита дважды (в том же самом контексте).

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

Первые два элемента закодированы битом в однобайтовый "заголовок", и переданы в полосе attr_definition_headers. Последние два элемента передаются как ссылки cp_Utf8 в соответствующих элементах attr_definition_name и attr_definition_layout. Таким образом есть три полосы, которыми компрессор объявляет типы атрибута к декомпрессору, и каждая полоса имеет длину #attr_definition_count.

  attr_definition_bands:
        *attr_definition_headers :BYTE1 [#attr_definition_count]
        *attr_definition_name :UNSIGNED5 [#attr_definition_count] (cp_Utf8)
        *attr_definition_layout :UNSIGNED5 [#attr_definition_count] (cp_Utf8)

Младшие значащие два бита байта заголовка определения атрибута обрабатываются как поле без знака, и дают тип контекста атрибута, который является типом объекта, к которому применяется атрибут:

(h & 0x03) Тип контекста
0 атрибут применяется к классам
1 атрибут применяется к полям
2 атрибут применяется к методам
3 атрибут применяется к атрибутам Кода

Старшие значащие шесть битов байта заголовка определения атрибута обрабатываются как поле без знака, и дают дополнительную позицию двоичного разряда, которой атрибут присваивается в слове флагов.

(h >> 2) Присвоение Флагового бита
0 переполните атрибута, не присвоенного любому биту
1 атрибут, присвоенный биту 0 (LSB lo слова)
2 атрибут, присвоенный биту 1
3 атрибут, присвоенный биту 2
...
32 атрибут, присвоенный биту 31 (MSB lo слова)
33 атрибут, присвоенный биту 32 (LSB привет слова)
...
63 атрибут, присвоенный биту 62
(никакое значение) бит 63 должен быть нулем (MSB привет слова)

У каждого атрибута class, предопределенный ли в этой спецификации или явно определенный компрессором, есть уникальное число, названное его атрибутом, индексируют. Если атрибут присваивается флаговый бит, то его атрибут индексирует, идентично позиции флагового бита (число в [0.. 62]). (Все предопределенные атрибуты присваиваются флаговый бит по умолчанию.)

Если атрибут class не присваивается флаговый бит, это - атрибут переполнения, и индексировать присваивается последовательно в порядке, в котором атрибуты class определяются (то есть, передаются). Первые индексируют, чтобы быть присвоенными, последовательно таким образом 32, если #have_class_flags_hi является четким, и 63, если он устанавливается. Они индексируют, используются в пределах архива, чтобы объявить возникновения атрибута для отдельных классов.

Аналогично, поле, метод, и атрибуты кода присваиваются, их собственный атрибут индексирует, независимо от атрибутов class и друг друга. Поэтому, атрибут (то есть, имя и пара расположения) уникально определяется в пределах архива его типом контекста, и атрибут индексируют. Поле и атрибуты метода могут быть присвоены флаговым битам, или иначе они - атрибуты переполнения с, индексирует 32 или больше. Как другие атрибуты, атрибуты кода могут быть присвоены явные числа или неявно присвоены, индексирует запуск с 32. (Как с атрибутами class, если высокие полосы слова флага выбираются соответствующим битом #archive_options, то поле, метод, или кодируют атрибуты переполнения, имеют, индексирует 63 или больше.)

Некоторые атрибуты предопределяются, и не требуют, чтобы компрессор испустил определения для них. Они неявно определили разметки и присвоения флагового бита (то есть, индексирует).

Атрибут индексирует, меньше чем 63 применимы во всех случаях, но они могут конфликтовать с присвоенными предопределенным атрибутам, включая предопределенные определенные атрибуты (в диапазоне 16 - 62) в будущих расширениях формата Pack200. В существующей версии все предопределенные атрибуты имеют, индексирует в диапазоне [17.. 31], так, чтобы флаги модификатора не были приняты по умолчанию, и высоко отметили слова, не должны обычно использоваться.

Здесь имена и индексируют присвоения предопределенных атрибутов. (Предопределенные разметки даются ниже.)

Индексировать Тип контекста Имя
16 C, F, М. (переполните атрибутов),
17 Класс SourceFile
18 Класс EnclosingMethod
19 C, F, М. Подпись
20 C, F, М. Устаревшие
21 C, F, М. RuntimeVisibleAnnotations
22 C, F, М. RuntimeInvisibleAnnotations
23 Класс InnerClasses
24 Класс "class - версия файла"
17 Поле ConstantValue
17 Метод Код
18 Метод Исключения
23 Метод RuntimeVisibleParameterAnnotations
24 Метод RuntimeInvisibleParameterAnnotations
25 Метод AnnotationDefault
0 Код StackMapTable
1 Код LineNumberTable
2 Код LocalVariableTable
3 Код LocalVariableTypeTable
16 Код (переполните атрибутов),

Бит 16 предопределяется как индикатор присутствия атрибутов переполнения для классов, полей, методов, и кодов. Если у объекта будут атрибуты переполнения, то он будет обладать соответствующим количеством в "attr_count" полосе, и каждый атрибут переполнения будет частью выполнения значений в "attr_indexes" полосе, которая определяет разметки атрибутов переполнения. Эта обработка атрибутов переполнения описывается более полно ниже.

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

Определенные биты предопределяются, чтобы поддерживать пять типов атрибутов метаданных на классах, полях, и методах, RuntimeVisibleAnnotations, RuntimeInvisibleAnnotations, RuntimeVisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations, и AnnotationDefault. (Последние три типа применяются только к методам.) Значение и формат этих атрибутов определяются JSR 175.

Допустимо для компрессора воздержаться от установки битов в любых словах флага за исключением бита 16, и передать все расположение атрибута индексирует явно в class_attr_indexes или подобной полосе. Декомпрессоры обязаны обрабатывать любой вид возникновения атрибута, индексируют. (Также допустимо, хотя бесполезный, для количества атрибута быть явно передано как нуль.) Компрессоры поощряются сделать умный выбор и очистить бит 16 и установить другие присвоенные флаговые биты когда возможный.

Отметьте, что ни один из предопределенных битов не вмешивается ни в какие настоящие или будущие флаговые биты в 16-разрядных флаговых значениях, сохраненных в формате файла class. Однако, компрессоры свободны снова использовать один из младшего разряда 16 битов слова флагов, связывая их с другими атрибутами, если никакой файл фактически не устанавливает их.

Атрибут InnerClasses обрабатывается особенно, как задокументировано в другом месте, и это - ошибка для компрессора, чтобы испустить определение атрибута для этого в контексте class. Атрибут Code также обрабатывается особенно. Это - ошибка испустить определение атрибута для этого в контексте метода.

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

5.5.2. Определения Расположения атрибута
Разметки атрибута управляют компрессором, поскольку он анализирует тела атрибута от файлов class в наборы скалярных значений. Разметки также управляют декомпрессором, поскольку он декодирует переданные полосы тех скалярных значений, и хранит их, правильно форматированный, в файлы class. Например, когда class хранилища файлов целое без знака в двух байтах (в порядке с обратным порядком байтов) в атрибуте, декомпрессор использует объявление расположения с этой целью, так, чтобы это могло взять элемент полосы (который является 32-разрядным целым числом, которое в этом случае, оказывается, меньше чем 65536), и сохраните это правильно в файл class. Передача такого целого числа очень отличается от передачи постоянной ссылки пула, даже при том, что они появляются как недифференцируемые байты в формате файла class.

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

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

Самое простое применимое расположение атрибута было бы последовательностью постоянных ссылочных объявлений пула, смешанных с однобайтовыми объявлениями, чтобы управлять всем остальным, и компрессоры свободны использовать такие разметки, чтобы описать атрибуты. Однако, более определенные разметки атрибута приводят к лучшему сжатию.

Атрибуты обычно содержат постоянные ссылки пула и маленькие целые числа. Они часто содержат целые числа, которые управляют репликацией последующих образцов. Постоянные ссылки пула со строгим контролем типов где только возможно, и условие кодирования для нулевых ссылок должно быть объявлено также. Маленькие целые числа, которые кодируют флаговые биты или байт-код, индексируют, также объявляются как таковым, так, чтобы специальные методы кодирования могли использоваться на них.

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

  attribute_layout:
        ( layout_element )* | ( callable )+
  layout_element:
        ( integral | replication | union | call | reference )

  callable:
        '[' body ']'
  body:
        ( layout_element )+

  integral:
        ( unsigned_int | signed_int | bc_index | bc_offset | flag )
  unsigned_int:
        uint_type
  signed_int:
        'S' uint_type
  any_int:
        ( unsigned_int | signed_int )
  bc_index:
        ( 'P' uint_type | 'PO' uint_type )
  bc_offset:
        'O' any_int
  flag:
        'F' uint_type
  uint_type:
        ( 'B' | 'H' | 'I' | 'V' )

  replication:
        'N' uint_type '[' body ']'

  union:
        'T' any_int (union_case)* '(' ')' '[' (body)? ']'
  union_case:
        '(' union_case_tag (',' union_case_tag)* ')' '[' (body)? ']'
  union_case_tag:
        ( numeral | numeral '-' numeral )
  call:
        '(' numeral ')'

  reference:
        reference_type ( 'N' )? uint_type
  reference_type:
        ( constant_ref | schema_ref | utf8_ref | untyped_ref )
  constant_ref:
        ( 'KI' | 'KJ' | 'KF' | 'KD' | 'KS' | 'KQ' | 'KM' | 'KT' | 'KL' )
  schema_ref:
        ( 'RC' | 'RS' | 'RD' | 'RF' | 'RM' | 'RI' | 'RY' | 'RB' | 'RN' )
  utf8_ref:
        'RU'
  untyped_ref:
        'RQ'

  numeral:
        '(' ('-')? (digit)+ ')'
  digit:
        ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
 

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

Каждое значение, которым управляет элемент расположения атрибута, преобразовывается компрессором в 32-разрядное значение и передается как элемент полосы, уникально создаваемой для, и управляло тем элементом расположения. Для элементов расположения integral преобразование просто представляет число, сохраненное в файле class под данным типом, в то время как элементы reference преобразовывают локальную постоянную ссылку пула (локальный для файла class, который является) в глобальную переменную, типизированную ссылку в пределах архива.

Многократные возникновения того же самого вида элемента расположения расцениваются как отличные элементы расположения. Кроме того, полосы никогда не совместно используются разметками. Поэтому, каждое новое определение расположения, переданное компрессором неявно, определяет свой собственный набор полос. Переприсвоение ранее определенного расположения атрибута к новому индексирует, создает новый набор полос; это не снова использует ранее определенные наборы полос.

Если компрессор определяет новые атрибуты, он должен также создать полосы, которыми они управляют. Это должно передать эти полосы, сразу после места, зарезервированного в грамматике полосы для предопределенных атрибутов (в конце class_attr_bands, field_attr_bands, method_attr_bands, или code_attr_bands). Упорядочивание этих полос должно соответствовать порядку определения элементов расположения атрибута, которые управляют ими. Таким образом декомпрессор будет в состоянии найти те значения атрибута.

Порядок определения двух элементов расположения в той же самой строке расположения атрибута соответствует их порядку возникновения в пределах той строки. Порядок определения двух элементов расположения не в той же самой строке расположения атрибута соответствует индексировать порядку их определений расположения в полосе attr_definition_layout. (Таким образом, полосы для разметок с ниже индексируют, предшествуют полосам для разметок того же самого типа контекста, но с выше индексирует. Это - истина, даже если ниже индексированное расположение, оказывается, определяется позже в полосе attr_definition_layout.) Отмечают, что полосы, которыми управляют предопределенные атрибуты, кажется, следуют за таким упорядочиванием также. Однако, полосы предопределенных атрибутов class предшествуют всем другим полосам атрибута class, и аналогично для полей, методов, и кодируют атрибуты.

Целочисленные значения, сохраненные в атрибутах, измеряются как 1, 2, или 4 байта, в зависимости от использования символа формата 'B', 'H', или 'я', соответственно. Целочисленный тип обычно без знака, но снабжается префиксом 'S', становится подписанным. Это подписание управляет удлинением 1-байтовых и 2-байтовых типов к 32-разрядным значениям (или расширение знака или нулевое заполнение). Это также определяет основное кодирование, используемое, чтобы передать 32-разрядные значения. Поскольку все целые числа, сохраненные в файлах class, являются "обратным порядком байтов", все интегральные элементы формата обращаются к целым числам, кодированным с битами высшего порядка в более ранних байтах.

Разметки Integral (то есть, те элементы под нетерминальным integral) управляют значениями подписанного или целого без знака. Интегральные разметки, объявления которых включают символы 'P' или 'O', используют специальные основные кодировки (BCI5 или BRANCH5) как описано ниже. Любые другие интегральные разметки, объявления которых включают символ 'S', управляют полосами с основным кодированием SIGNED5. Целое без знака и элементы расположения флага управляют полосами с основным кодированием UNSIGNED5, за исключением того, что целочисленное расположение 'B' (байт без знака) управляет полосой с основным кодированием BYTE1.

(Отметьте, что нет никакого специального кодирования для подписанных байтов. Если атрибут содержит подписанное поле байта, это может быть точно также, чтобы обработать то поле, как будто это было без знака, и дает этому простой 'Б' элемент расположения. Помимо законченности, расположение 'СУРЬМЫ' предназначается, чтобы позволить маленькой величине однобайтовые целые числа, которые будут переданы, используя алфавит байта, в котором знаковые биты редки. Это является требуемым, когда компрессор постпередачи использует Кодирование методом Хаффмана, чтобы представить байты; такие codings выполняют лучше всего, когда непротиворечивый алфавит байта представляется компрессору.)

Сохраненный байт-код индексирует, объявляется с префиксом расположения 'P'. Этот элемент расположения может только использоваться на методах или кодах. Любое число может быть сохранено в байт-коде, индексируют. Однако, прежде, чем сохраненные числа передаются как элементы полосы, они перенумеровываются в ожидании, что позиции байта не на границах инструкции будут редки.

BCI, перенумеровывающий сжато, индексирует границы инструкции, и также обеспечивает кодирование (несколько менее компактное) для всех других 32-разрядных целых чисел, таких как адреса байтов в инструкциях или вне границ байт-кодов. В частности первый байт первой инструкции нумеруется нуль, первый байт второй инструкции нумеруется один, и так далее через все инструкции. Байт располагает одно прошлое, последняя инструкция нумеруется со следующим числом (число инструкций). Второй байт первой многобайтовой инструкции нумеруется со следующим числом, которое является еще одним чем число всех инструкций. Все остающиеся непронумерованные байты присваиваются последующие числа без дальнейших беспорядков упорядочивания. Для достаточно больших положительных чисел, и для отрицательных чисел, изменение нумерации является тождественным отображением.

В целях определить местоположение границ инструкции для изменения нумерации BCI, _wide байт-код (0xc4) берется, чтобы быть частью следующих инструкций, формат которых это помогает определить. Если компрессор передает byte_escape (254) или ref_escape (253) псевдоинструкции, декомпрессор должен принять последовательности байт-кода, произведенные каждой из этих инструкций как интегральные инструкции, когда вычислительный BCI renumberings. Таким образом будет граница инструкции для каждого байта в bc_codes (кроме _wide байт-кодов) плюс дополнительная граница для каждого "aload_0_xxx" изменения (таких как "aload_0_getstatic_this"), потому что эти псевдокоды операций расширяются до пар инструкций байт-кода.

Пожалуйста, см. раздел Приложения для псевдокода, объясняя это понятие.

Если элемент расположения снабжается префиксом 'P' и не 'ПО', то перенумерованный байт-код индексирует, передается. Это изменение нумерации вызывают, байт-код индексирует изменение нумерации. Основное кодирование для полос, содержащих байт-код, индексирует, BCI5.

Вот пример того, как это работает. Вообразите метод с 20 байтами данных байт-кода и пяти инструкций в следующих позициях: { 0, 4, 6, 10, 17 }. Изменение нумерации BCI преобразовывает эти определенные числа сжато в [0..4]. Более полностью изменение нумерации BCI преобразовывает [0..20] в числа { 0, 6, 7, 8, 1, 9, 2, 10, 11, 12, 3, 13, 14, 15, 16, 17, 18, 4, 19, 20, 5 }, и что-либо вне диапазона, [0..20] остается то же самое после изменения нумерации BCI. Если атрибут этого метода будет иметь элемент расположения 'P', и сохранит номер 6 в файле class, то номер 2 будет передан, с тех пор 6 смещение третьей инструкции.

Если префиксом расположения является 'ПО', предыдущий элемент расположения, должно быть, также был байт-кодом, индексируют типа 'P' расположения или 'ПО'. (Там не должен вмешиваться структура, такая как скобки' [' или']'.) В этом случае значение, переданное в полосе, которой управляет элемент 'ПО', является различием между перенумерованным байт-кодом, индексируют управляемый текущим элементом 'ПО', и перенумерованный байт-код индексирует управляемый предыдущим 'P' или элементом 'ПО'. (В случае предыдущего элемента 'P' это - фактически значение, переданное в соответствующей позиции в предыдущей полосе.)

Элементы расположения 'ПО' управляют тем же самым видом данных атрибута как элементы 'P', но они используют кодирование, которое ожидает, что смежный байт-код индексирует, коррелируются. Это изменение нумерации, включая различие для предыдущего элемента, вызывают, смещение байт-кода, перенумеровывая основное кодирование для полос, содержащих смещения байт-кода, является BRANCH5. Это кодирование используется, даже если элемент расположения содержит 'S' или символ 'B'.

Смещение байт-кода объявляется с префиксом расположения 'O'. Этот элемент расположения должен сразу следовать, предыдущий байт-код индексируют элемент (с префиксным 'P' и не 'ПО'). Любое значение, которым управляет этот элемент расположения, расценивается как смещение, которое когда применено к индексирует соответствующий ранее сохраненный байт-код, производит другой байт-код, индексируют. Таким образом, и предыдущее значение и сумма предыдущего значения и текущей стоимости, как ожидают, обратятся к границам инструкции. Как с расположением 'ПО', переданное значение является различием двух перенумерованных байт-кодов, индексирует. Полосы, которыми управляют разметки 'ПО', содержат смещения байт-кода, и используют основное кодирование BRANCH5. В отличие от расположения 'ПО', хранимая сумма, которой управляет расположение 'O', является различием между двумя байт-кодами, индексирует.

Таким образом полосы, которыми управляют и 'O' и разметками 'ПО', содержат смещения байт-кода, и используют BRANCH5, чтобы закодировать те смещения. Но значения атрибута, которыми управляют и 'P' и абсолютным байт-кодом хранилища разметок 'ПО', индексируют; только разметки 'O' управляют сохраненными смещениями байт-кода. Сохраненные смещения обрабатываются как поля без знака в файле class, если символ 'S' не присутствует. В отличие от этого, сохраненный индексирует, всегда обрабатываются как поля без знака.

Если у предыдущего атрибута в качестве примера для 20-байтового метода также есть элемент расположения 'ПО' после его элемента 'P', и номер 20 сохранен в файле class, число, которое будет передано, находится, перенумеровывая от 20 до 5, и затем вычитая предыдущий переданный номер (5-2). Номер 3 будет поэтому передан. Если вместо этого сохраненное число будет 7 (BCI в инструкции в позиции 6), то переданное число будет (10-2) или 8. Те же самые переданные значения (3, 8), если бы управляющийся элементом расположения 'O' вместо 'ПО', соответствовали бы сохраненным значениям 14 (20-6) и 1 (7-6), вместо 20 и 7.

Элемент флага (с префиксным 'F') кодирует целочисленные значения, которые, как ожидают, закодируют короткий массив битов, а не арифметические значения. Биты не обязаны быть интерпретированными как модификаторы доступа. Основное кодирование для полос, передающих элементы расположения флага, является UNSIGNED5, за исключением того, что разметки 'FB' используют основное кодирование BYTE1.

Интегральные значения, переданные под 'V' символ формата вместо 'B', 'H', или 'я' не занимаю байтов вообще в атрибуте файла class. Эти элементы расположения позволяют декомпрессору использовать количества, или теги, чтобы управлять передачей, не имея их появляются непосредственно в атрибутах файла class. Например, рассмотрите атрибут, который является массивом байтов, который не самоизмеряет, но расширяется, чтобы заполнить количество байта, упомянутое в заголовке атрибута в файле class. У такого атрибута могла бы быть спецификация расположения 'NV [B]'. Компрессор был бы ответственен, чтобы решить который значения передать для 'V' элемент расположения. (Такие решения должны были бы использовать подробную информацию о форматах атрибута, которая не является частью этой спецификации.) Во всех случаях декомпрессор должен уважать эти значения (когда использующийся в качестве количеств или тегов), но не должен сохранить их в файле class.

Репликация представляется префиксным 'N', который сопровождается целочисленным элементом, названным количеством репликации, и к тому времени серия элементов, названных телом репликации, включила в квадратные скобки. Данные атрибута, которыми управляет это расположение, состоят из количества репликации, сопровождаемого массивом данных, считаемых количеством репликации. Каждым элементом массива управляют разметки в теле репликации.

Элемент расположения количества репликации управляет полосой, передающей количества репликации, у которого есть основное кодирование UNSIGNED5 (или BYTE1, если расположение запускается с 'NB'). Полосы, которыми управляет соответствующее тело репликации, могут быть измерены, суммируя значения, переданные в полосе, содержащей количества.

Объединение представляется префиксным 'T', который сопровождается целочисленным элементом, названным тегом объединения, и к тому времени серией маркированных, заключенных в скобки групп элементов, названных случаями объединения. (У цифр может быть любое число цифр, но их арифметические значения являются усеченными к 32-разрядным целым числам перед стать по сравнению со значениями полосы, которые также составляют 32 бита в размере.) Каждая метка, но последнее состоит из один или более заключенный в скобки, возможно подписанные десятичные цифры, названные тегами объединения. Последняя метка (который является случаем значения по умолчанию) должна быть пустой парой круглых скобок. (Никакое объединение не может содержать два возникновения того же самого тега случая.) Данные атрибута, которыми управляет это расположение, состоят из интегрального значения тега, сопровождаемого данными, формат которых определяется тегом. Данными после тега управляет (уникальный) случай объединения, метка которого соответствует значение тега, или иначе случай значения по умолчанию. Полосы, которыми управляет каждый случай объединения, могут быть измерены, считая число значений в полосе, которой управляет расположение тега. Как с простыми интегральными полосами, основное кодирование полосы тега объединения является SIGNED5, BYTE1, или UNSIGNED5, в зависимости от того, содержит ли расположение символ 'S', 'Тбайт', или иначе.

В теге объединения две цифры, разделенные дефисом, определяют содержащий диапазон. Второе число должно быть больше чем первое. Это - сокращение для списка всех цифр сначала к второму, включительно. Расположение обрабатывается точно, как будто сокращение было заменено полным списком.

Постоянные ссылки пула в атрибуте могут быть введены строго, и переданы, как индексирует в один из постоянных пулов архива. Типы расположения, начинающиеся 'с КИ', 'КИЛОДЖОУЛИ', 'KF', 'KD', и 'KS', должны управлять сохраненный, индексирует в локальном постоянном пуле к константам целого числа типа, долго, плавания, дважды, и строки. Расположение вводит beginnig 'KM', и 'KT' управляют, индексирует к константам типа MethodHandle и MethodType. Аналогично, типы расположения, начинающиеся 'с RC', 'РТС ', RD', 'RF', 'КОМНАТА', 'RI', и 'RU' должны управлять сохраненный, индексирует в локальном постоянном пуле к символам типа class, подпись, дескриптор (пара имени и вводят), полевая ссылка, ссылка метода, ссылка метода интерфейса, и строка UTF8. Тип расположения 'РАЙ' управляет, индексирует к invokedynamic дескрипторам, в то время как тип 'RB' управляет, индексирует, чтобы загрузить спецификаторы метода (которые являются элементами атрибута BootstrapMethods, не постоянного пула). Все эти ссылки передаются, поскольку 32-разрядный индексирует в соответствующие глобальные постоянные пулы, в полосах с основным кодированием UNSIGNED5. (Это - истина даже разметок, которые содержат 'B'.) См. таблицу ниже.

Отметьте, что ссылки подписи (расположение 'РТС) идентичны ссылкам Utf8 (расположение 'RU') в пределах файла class, но приводят к различной тактике кодирования в архивном файле, начиная с cp_Utf8 и cp_Signature, который постоянные пулы имеют независимый, индексирует и передаются по-другому.

Элементы расположения, начинающие 'KQ', могут только произойти в атрибутах на полях. Они обращаются к константам в постоянном пуле, идентификационные данные которого определяются подписью поля. (Этот элемент расположения, вероятно, полезен только для атрибутов ConstantValue, которые предопределяются.) Следующая таблица дает полевые подписи, законные для использования с разметками 'KQ', и соответствующих постоянных пулов, в которых должны быть найдены соответствующие сохраненные ссылки.

Полевая Подпись 'KQ' Постоянный Пул
B cp_Int
S cp_Int
C cp_Int
Z cp_Int
Я cp_Int
J cp_Long
F cp_Float
D cp_Double
Ljava/lang/String; cp_String
Ljava/lang/Class; cp_Class

Три дополнительных передачи типов расположения индексируют в постоянные группы пула вместо отдельных постоянных пулов. Они могут использоваться, когда компрессор выбирает использовать расположение, у которого есть ссылки, которые не со строгим контролем типов. Объединенный тип 'KL' может использоваться для любого, индексируют, который обращается к допустимому операнду 'ldc' инструкции, и переданный индексирует, будет перенумерован относительно группы пула cp_LoadableValue. Точно так же объединенный тип расположения 'RN' может использоваться для любого, индексируют, который обращается к допустимому операнду любого того, 'чтобы получать', или 'вызовите' инструкции (кроме 'invokedynamic'), и они индексируют, будет перенумерованный относительно группы пула cp_AnyMember.

Наконец, если постоянная ссылка пула не может быть введена вообще, компрессор должен использовать untyped_ref ('ЗАПРОС'), который передает индексирование во всестороннюю постоянную группу пула cp_All. Например, все элементы пула cp_Utf8 нумеруются то же самое в разметках 'RU' и 'ЗАПРОСЕ'. Но первый элемент (нуль элемента) пула cp_Int нумеруется, для нетипизированных ссылок, как cp_Utf8_count, и первый элемент пула cp_Float нумеруется, для нетипизированных ссылок, как cp_Utf8_count+cp_Int_count.

Если компрессор сталкивается с атрибутом, который содержит постоянный пул, индексируют неожиданного типа, он может или отказаться передать атрибут, или выбрать передавать атрибут в соответствии с ослабленным определением расположения, используя 'ЗАПРОС' или элементы 'RQN' вместо большего количества элементов со строгим контролем типов. (Если неожиданный тип является загружаемой константой или задействованной ссылкой, компрессор может выбрать использовать 'RN' или элементы 'KL' вместо этого.) Декомпрессоры обязаны соблюдать все юридические определения расположения, переданные компрессорами, даже если они могли бы произвести, незаконно отформатировал файлы class. (В крайнем случае компрессор может выбрать передавать файл class, как будто это был файл ресурсов, не получая class специфичное сжатие, но сохраняя необычно отформатированные атрибуты с поразрядной точностью.)

Если тип расположения reference включает символьный 'N', все значения полосы, кодирующие постоянные записи пула, постепенно увеличиваются одним, и нулевое значение кодируется как нуль. Иначе, нулевое значение кодируется как отрицательное один (-1).

Эффект на основные кодировки полосы правил, данных выше, может быть получен в итоге как список расположенных по приоритетам правил для элементов расположения, где первое применимое правило определяет кодирование:

Вот таблица, суммирующая полосы и кодировки для различных элементов расположения. (Не все возможные комбинации типов и целочисленных размеров показывают.)

Расположение
Элемент
Сохраненный
Значение
Переданный
Значение
Основной
Кодирование
B u1 x BYTE1
FB u1 x BYTE1
СУРЬМА u1 (байт) x SIGNED5
H u2 x UNSIGNED5
FH u2 x UNSIGNED5
SH u2 (короткий) x SIGNED5
Я u4 x UNSIGNED5
FI u4 x UNSIGNED5
SI u4 x SIGNED5
PH ФАКТОР u2 renumber_bci (x) BCI5
POH u2 renumber_bci (x) - renumber_bci (x0) BRANCH5
OH u2 renumber_bci (x0+x) - renumber_bci (x0) BRANCH5
NB [...] u1 x (также служит количеством размера), BYTE1
NH [...] u2 x (также служит количеством размера), UNSIGNED5
NI [...] u4 x (также служит количеством размера), UNSIGNED5
ТБАЙТ... u1 x BYTE1
TSB... u1 (байт) x SIGNED5
TH... u2 x UNSIGNED5
TSH... u2 (короткий) x SIGNED5
КИБИБАЙТ u1 indexOf (lcp [x], cp_Int) UNSIGNED5
KIH u2 indexOf (lcp [x], cp_Int) UNSIGNED5
KII u4 indexOf (lcp [x], cp_Int) UNSIGNED5
KINH u2 1+indexOf (lcp [x], cp_Int) UNSIGNED5
KJH u2 indexOf (lcp [x], cp_Long) UNSIGNED5
KFH u2 indexOf (lcp [x], cp_Float) UNSIGNED5
KDH u2 indexOf (lcp [x], cp_Double) UNSIGNED5
KSH u2 indexOf (lcp [x], cp_String) UNSIGNED5
KQH u2 indexOf (lcp [x], cp_FieldSpecific) UNSIGNED5
КМ/Ч u2 indexOf (lcp [x], cp_MethodHandle) UNSIGNED5
KTH u2 indexOf (lcp [x], cp_MethodType) UNSIGNED5
KLH u2 indexOf (lcp [x], cp_LoadableValue) UNSIGNED5
RCH u2 indexOf (lcp [x], cp_Class) UNSIGNED5
RSH u2 indexOf (lcp [x], cp_Signature) UNSIGNED5
RDH u2 indexOf (lcp [x], cp_Descr) UNSIGNED5
RFH u2 indexOf (lcp [x], cp_Field) UNSIGNED5
RMH u2 indexOf (lcp [x], cp_Method) UNSIGNED5
RIH u2 indexOf (lcp [x], cp_Imethod) UNSIGNED5
RUH u2 indexOf (lcp [x], cp_Utf8) UNSIGNED5
RQH u2 indexOf (lcp [x], cp_All) UNSIGNED5
RQNH u2 1+indexOf (lcp [x], cp_All) UNSIGNED5
RQNI u4 1+indexOf (lcp [x], cp_All) UNSIGNED5
RYH u2 indexOf (lcp [x], cp_InvokeDynamic) UNSIGNED5
RBH u2 indexOf (class.BootstrapMethods [x], cp_BootstrapMethod) UNSIGNED5
RNH u2 indexOf (lcp [x], cp_AnyMember) UNSIGNED5

Здесь, переменная x называет значение сохраненным в атрибуте, которым управляет элемент расположения. Переменная x0 называет хранимую сумму управляемой сразу предыдущим элементом расположения, который, должно быть, начался 'с P'. Выражение renumber_bci (x) обозначает, что изменение нумерации байт-кода индексирует x, чтобы сократить ссылки на границы инструкции, как описано выше. Выражение lcp [x] обозначает, что локальная постоянная ссылка пула, с индексируют x, или отличное нулевое значение, если x является нулем.

Выражение class.BootstrapMethods [x] обозначает элемент атрибута BootstrapMethods текущего class. Этот атрибут содержит дополнительные сложные константы, требуемые CONSTANT_InvokeDynamic постоянные записи пула.

Выражение indexOf (lcp [x], cp) обозначает индексирование (основанного на нуле) в глобальном постоянном cp пула Pack200 постоянного lcp [x], который, как предполагается, имеет тип, соответствующий cp. У этого выражения есть значение-1, если у lcp [x] есть отличное нулевое значение.

Отметьте, что нулевая ссылка может всегда передаваться в полосе, содержащей ссылки, передавая нуль значения (если полоса определяется, чтобы принять, обнуляет), или передавая значение-1 (иначе). Кодирование UNSIGNED5 может представить-1 в пяти байтах.

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

5.5.3. Рекурсивные Разметки
Высокоуровневая структура спецификации расположения может быть серией тел, которые являются независимо вызываемыми разметками. В таком случае данными атрибута, которыми управляет целая спецификация расположения, управляет первое тело в последовательности callables. Другой callables может управлять данными, но они только делают это, если их фактически вызывают. Эффект состоит в том, чтобы определить взаимно рекурсивное множество спецификаций расположения, и дать контроль к первому. Отметьте, что callables не может быть вложен ни в каком другом синтаксисе. Эта функция полезна для поддержки, рекурсивно структурировал атрибуты файла class, такие как метаданные.

Элемент расположения вызова является заключенной в скобки подписанной десятичной цифрой N. Это обращается к Энному вызываемому в высокоуровневой структуре спецификации расположения относительно вызываемого, в котором появляется вызов. (Это недопустимо для вызовов, чтобы появиться за пределами callables.) Мы обратимся к этому вызываемому как вызываемый вызова.

(Например, элемент расположения' (2)' вызовы второе вызываемое расположение после того, в котором появляется вызов. Должен быть соответствующий вызываемый для каждого вызываемого. Вызов, записанный' (1)', не должен появиться в последнем вызываемом из расположения, и аналогично вызов, записанный' (-1)', не должен произойти в первом вызываемом. Отметьте, что самовызов, записанный' (0)', является всегда законным.)

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

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

Если вызываемый вызова начинает дословно позже чем вызов непосредственно, вызов является переводить вызовом. Эффект переводить вызова состоит в том, чтобы просто сделать полосы вызываемого с обеспечением совместного доступа вызовом и любыми другими прямыми звонками в того же самого вызываемого. Например, у следующей спецификации расположения есть две полосы, последний которых передает данные, которыми косвенно управляет любой из случаев объединения. (Случай объединения значения по умолчанию не управляет никакими полосами, так, чтобы у байта тега кроме ASCII или 'B' не было никакого после байтов. Пробел был добавлен к расположению для простоты чтения.)

        [TB
          (65) [(1)]
          (66) [(1)]
          (  ) []
          ]
        [H]
 

Вызываемый вызова может также начать дословно ранее чем вызов непосредственно. Такой вызов, у которого должно быть написание формы' (0)' или' (-N)', упоминается как обратный вызов. Его вызываемый упоминается как обратное вызываемое. (Callables, которые являются целью никаких вызовов или только, переводят вызовы, не обратный callables; все другие.) Назад вызывает, и callables представляют возможность рекурсии и цикличного выполнения. Вот пример дерева Не, листы которого являются строками Utf8, которым предшествует нулевой байт, и чьи внутренние узлы считаются массивы древовидных узлов, которым предшествуют однобайтовым: В этом примере вызываемый включает вызов для прямой рекурсии. Расположение управляет тремя полосами, под элементами 'Тбайт', 'NH', и 'RUH'.

        [TB
          (1) [NH[ (0) ]]
          (0) [RUH]
        ]
 

Калибровке полос, которыми управляют такие взаимно рекурсивные разметки, помогают явные количества обратных вызовов, переданных перед любой из полос атрибута расположения, в class_attr_calls и трех подобных полосах, которые описываются позже.

5.5.4. Разметки Атрибута по умолчанию
Определения расположения предопределенных атрибутов следующие:
Тип контекста Имя Определение расположения
Класс "class - версия файла" (пустой) * (см. примечание),
Класс InnerClasses (пустой) * (см. примечание),
Класс EnclosingMethod RCHRDNH
Класс SourceFile RUNH * (см. примечание),
Класс Подпись RSH
Класс (метаданные) (см. ниже),
Класс Устаревшие (пустой)
Поле ConstantValue KQH
Поле Подпись RSH
Поле (метаданные) (см. ниже),
Поле Устаревшие (пустой)
Метод Код (пустой) * (см. примечание),
Метод Исключения NH [RCH]
Метод Подпись RSH
Метод (метаданные) (см. ниже),
Метод Устаревшие (пустой)
Код StackMapTable (см. ниже),
Код LineNumberTable NH [PHH]
Код LocalVariableTable NH [PHOHRUHRSHH]
Код LocalVariableTypeTable NH [PHOHRUHRSHH]

Звезда '*' в определениях расположения "class - версия файла", InnerClasses, SourceFile, и Code отражают факт, что этим атрибутам дают специальную обработку. Для class "class - передается псевдоатрибут" версии файла, как будто используя формат VV, но декомпрессор не хранит результат в атрибуте файла class, а скорее в заголовке файла class. (См. обсуждение ниже.) Для class частично передается атрибут InnerClasses, как будто используя формат NV[RCVTV[(0)[]()[RCNVRUNV]]], но декомпрессор обрабатывает полученные значения далее прежде (возможно) испустить атрибут InnerClasses. (См. обсуждение ниже.), Когда атрибут SourceFile передается, используя предопределенное расположение, специальное правило позволяет этому принимать значение по умолчанию к очевидной стандартной строке. Наконец, для метода, атрибут Code передается под code_bands.

5.5.5. Разметки Карты стека
Есть предопределенное расположение атрибута для атрибута StackMapTable атрибута Code. С некоторым пробелом и сокращением, добавленным для удобочитаемости, это следующие:

  [NH[(1)]]
  [TB
    (64-127)  [(2)]
    (247)     [(1)(2)]
    (248-251) [(1)]
    (252)     [(1)(2)]
    (253)     [(1)(2)(2)]
    (254)     [(1)(2)(2)(2)]
    (255)     [(1)NH[(2)]NH[(2)]]
    ()        []
    ]
  [H]
  [TB
    (7) [RCH]
    (8) [PH]
    ()  []
    ]
 

Следующие наблюдения могут быть выведены, сравнивая эту спецификацию расположения со спецификацией формата файла class, которая определяет атрибут StackMapTable. Второе вызываемое описывает структуру stack_map_frame от спецификации формата файла class. В пределах объединения во втором вызываемом случаи поддерживают следующие члены профсоюза stack_map_frame, соответственно: same_locals_1_stack_item_frame, same_locals_1_stack_item_extended, chop_frame (и также same_frame_extended), append_frame (для трех случаев объединения расположения), full_frame, и (в случае объединения расположения значения по умолчанию) same_frame. Третьи и четвертые callables описывают значение offset_delta и структуру verification_type_info от спецификации формата файла class.

5.5.6. Разметки метаданных
Предопределенные разметки атрибута для аннотаций метаданных непараметра являются тем же самым во всех трех контекстах. С некоторым пробелом, добавленным для удобочитаемости, расположение следующие:

  [NH[(1)]]
  [RSH NH[RUH(1)]]
  [TB
    (66,67,73,83,90) [KIH]
    (68)  [KDH]
    (70)  [KFH]
    (74)  [KJH]
    (99)  [RSH]
    (101) [RSH RUH]
    (115) [RUH]
    (91)  [NH[(0)]]
    (64)  [RSH [RUH(0)]]
    ()    []
    ]
 
И видимые и невидимые аннотации используют это расположение. Второе вызываемое описывает структуру annotation от спецификации метаданных. Третье вызываемое описывает структуру member_value от спецификации метаданных. Это длится вызываемое, совершенно отдельно, используется для атрибута AnnotationDefault на методах. Аннотации параметра метода (и видимый и невидимый) также предопределяются, используя это расположение с предварительно ожидаемым вызываемым, чтобы считать число параметров:

  [NB[(1)]]
  [NH[(1)]]
  [RSH NH[RUH(1)]]
  [TB...]
 
5.5.7. Необычные Использования Расположения
Для компрессора возможно испустить любое число определений для того же самого названия атрибута. Эти определения присваиваются, различный атрибут индексирует (и возможно флаговые биты), и обрабатывается как отличные атрибуты, несмотря на наличие того же самого имени. Если атрибут слишком сложен, чтобы определить на языке расположения, каждому возникновению того атрибута может дать отдельное определение компрессор. Минимальное требование - то, что каждое расположение точно объявляет размер соответствующего возникновения атрибута, и определяет местоположение всех постоянных ссылок пула в пределах того возникновения.

5.6. Сокращение Исходного файла

Когда нулевая ссылка передается в полосе, которой управляет предопределенный атрибут SourceFile, декомпрессор обязан заменять это ссылкой на строку Utf8, написание которой состоит из связанной строки имени class, со следующими сделанными модификациями, в порядке:

Это правило соответствует историческое поведение многих компиляторов Java, и позволяет компрессору избегать выделять строки Utf8 для "очевидных" полученных имен SourceFile. (Если компрессор должен передать неправильный атрибут SourceFile с истинной нулевой ссылкой, он должен использовать нестандартное расположение.) Вот таблица примеров имен class и соответствующих полученных имен SourceFile.

Класс SourceFile
foo foo.java
foo/bar bar.java
foo/bar$baz bar.java
foo/bar#baz#1 bar.java
foo.bar.baz#1 baz.java

5.7. Вложенные Классы

Вложенная запись class является определением с четырьмя кортежами двух классов, имени, и некоторых флагов, как задокументировано для атрибута InnerClasses файлов class. Это прежде всего представляется в архиве Pack200 четырьмя полосами, содержание которых применяется одинаково ко всем файлам class в архиве.
  ic_bands:
        *ic_this_class :UDELTA5 [#ic_count] (cp_Class)
        *ic_flags :UNSIGNED5 [#ic_count]
        *ic_outer_class :DELTA5 [COUNT(1<<16,...)]  (null or cp_Class)
        *ic_name :DELTA5 [LENGTH(*ic_outer_class)] (null or cp_Utf8)
 
Эти четыре кортежа совместно используются глобально, как постоянные записи пула. В этой спецификации они - традиционно записанный <C,F,C2,N>, даже при том, что они сохранены в различном порядке в формате файла class. Как набор, эти глобально определенные четыре кортежа вызывают ic_All. обычно нет никакого явного редактирования от отдельных классов в архиве к вложенным записям class. Вместо этого извлекая файл class из архива Pack200, подмножество вложенных записей class может быть выбрано, который достаточен, чтобы описать все вложенные классы, фактически упомянутые в постоянном пуле файла извлеченного class. Для любого файла X class, который будет извлечен, это подмножество вызовут ic_Relevant(X), соответствующим подмножеством для X из ic_All. Алгоритм для того, чтобы выбрать соответствующее подмножество описывается позже. Дополнительно, компрессор может определить, для любого данного class, корректировки ее соответствующего подмножества, передавая локальный атрибут InnerClasses. Это также описывается в более позднем разделе по атрибутам class.

ic_this_class и полосы ic_flags имеют оба длину #ic_count, и соответствующие элементы этих полос определяют, для каждого кортежа, вложенные идентификационные данные class (представленный как ссылка cp_Class) и битовая маска флагов.

Вложенный флаговый бит class в позиции 16 (как установлено в маске 0x00010000) в архивном файле, чтобы указать, есть ли соответствующие записи для кортежа в полосах ic_name и ic_outer_class. Таким образом длина обеих из этих полос является суммой всех флаговых битов в позиции 16. Как правило, только несколько процентов вложенных классов должны установить этот бит и определить внешние и поля имени явно.

Если у кортежа есть запись в ic_outer_class и полосах ic_name, они определяют его внешний class и простое имя. (Они представляются соответственно как возможно нулевая ссылка cp_Class и возможно нулевая ссылка cp_Utf8.) Иначе, внешний class кортежа и имя, как говорят, предсказываются. В этом случае они должны быть правильно предсказуемыми с имени вложенного class непосредственно, анализируя его написание.

У вложенного class есть имя байт-кода, которое называет class в пределах файлов class. У написания этого имени, иногда называемого "скорректированным именем", есть дополнительные знаки пунктуации и возможно цифры так же как имя содержания class. Если имя байт-кода может быть проанализировано во внешний class и имя class, и этот class и имя идентичны с истинным внешним class и именем class вложенного class, то мы говорим, что внешний class и имя class предсказуемы.

Экстракция предсказуемого внешнего class и имени class должна следовать за следующей грамматикой для имен байт-кода class, в применении к написанию вложенного имени class. (Эта грамматика независима от грамматики, управляющей структурой полосы, или любой другой грамматикой, появляющейся в других частях этой спецификации.) Терминальный ДОЛЛАР обращается к любому символу (такому как '$' или '#'), чей код является 0x2D или ниже. НАКЛОННАЯ ЧЕРТА терминалов обращается к наклонной черте или точечным символам '/' или'.', у которых есть коды 0x2E и 0x2F. Терминальная ЦИФРА обращается к десятичной цифре ASCII, одному из десяти символьных кодов от 0x30 до 0x39 включительно. Терминальная БУКВА обращается к любому другому символу. Таким образом, это обращается к любому символу, код которого является 0x3A или выше.

  bcn:
        (bcnCase1 | bcnCase2 | bcnCase3 | bcnCase4)
  bcnCase1:
        packageQual (namePart)? DOLLAR number
  bcnCase2:
        packageQual (namePart)? DOLLAR number DOLLAR predictableICName
  bcnCase3:
        predictableOuter DOLLAR predictableICName
  bcnCase4:
        packageQual (namePart)?

  predictableOuter:
        packageQual namePart
  predictableICName:
        LETTER (LETTER | DIGIT)*

  namePart:
        (LETTER | DIGIT | DOLLAR)+
  number:
        (DIGIT)+
  packageQual:
        (namePart SLASH)*
 

Эта грамматика двусмысленно делит произвольное имя class на несколько частей, которые могут включать дополнительный префикс predictedOuter, дополнительный суффикс predictedICName, и дополнительный числовой суффикс. Любая неоднозначность должна быть разрешена, предпочитая альтернативные случаи для bcn, нетерминального в данном порядке. Например, если bcnCase1 соответствует, он используется, даже при том, что или или оба других случая может соответствовать также.

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

Если predictableOuter, внешний нетерминальный, анализируется, соответствующая строка является предсказуемым внешним именем class. Иначе предсказуемая внешняя ссылка class берется, чтобы быть нулем. Отметьте, что, если нетерминальный number анализируется, никакой predictableOuter не может быть проанализирован. Вот некоторые примеры прогноза, непрогноза, и misprediction:

Внутренние Примеры Прогноза Класса
вложенный class: элемент под названием Entry java/util/Map
скорректированное имя: java/util/Map$Entry
внешний, имя: java/util/Map, Entry
предсказуемый? да (так как Map.Entry является элементом Map),
вложенный class: анонимный
скорректированное имя: java/util/AbstractList$1
внешний, имя: (ни один), (ни один)
предсказуемый? да (так как ic_name является нулем),
вложенный class: лицо, не являющееся членом какой-либо организации, названное Local
скорректированное имя: java/util/AbstractList$2$Local
внешний, имя: (ни один), Local
предсказуемый? да (так как ic_name является Local),
вложенный class: лицо, не являющееся членом какой-либо организации, названное Local
скорректированное имя: java/util/AbstractList#2#Local
внешний, имя: (ни один), Local
предсказуемый? да (так как ic_name является Local),
вложенный class: элемент под названием $2$Local Foo
скорректированное имя: Foo$$2$Local
внешний, имя: (ни один), Local
предсказуемый? нет (внешние без вести пропавшие имени, ic_name mispredicted)
вложенный class: class по имени Red$Herring
скорректированное имя: Red$Herring
внешний, имя: Red, Herring
предсказуемый? нет (предсказанная ic_name Сельдь)
вложенный class: элемент под названием Q X$1
скорректированное имя: X$1$Q
внешний, имя: (ни один), Q
предсказуемый? нет (так как Q является элементом X$1),
вложенный class: элемент под названием Z X$Y
скорректированное имя: X$Y$Z
внешний, имя: X$Y, Z
предсказуемый? да (так как X$Y.Z является элементом X$Y),
вложенный class: элемент под названием Y$Z X
скорректированное имя: X$Y$Z
внешний, имя: X$Y, Z
предсказуемый? нет (внешнее имя и ic_name являются mispredicted),

Когда декомпрессор обрабатывает вложенное имя class, отмеченное "предсказуемый", он должен проанализировать имя байт-кода вложенного class во включение class, дополнительное число, и дополнительное имя. (Компрессор мог бы хотеть всегда определять внешние классы и имена явно, когда декомпрессор не будет обязан анализировать вложенные имена class вообще. Однако, декомпрессоры должны всегда готовиться выполнить этот парсинг.)

Если бы компрессор не передавал запись в cp_Utf8 или cp_Class для предсказанного имени или внешнего class, то декомпрессор должен создать такую константу внутренне. Это будет упоминаться как cp_Utf8 или запись cp_Class, даже при том, что это не находится в постоянной последовательности передачи cp_All. Однако, если бы компрессор действительно передавал константу с тем же самым написанием как предсказанное имя или внешний class, то декомпрессор должен использовать ту константу вместо того, чтобы создать новый. Создание таких внутренних констант в пределах декомпрессора обнаруживаемо в выходном файле, потому что они вставляются в специальный порядок в постоянном пуле выходного файла. (См. обсуждение выходных правил упорядочивания ниже.)

Пожалуйста, см. раздел Приложения для псевдокода, объясняя это понятие.

Когда декомпрессор получает ic_this_class, ic_flags, ic_name, и полосы ic_outer_class, и выполняет любой необходимый парсинг имени, это создает набор ic_All четырех кортежей. Этот набор является основным источником атрибутов InnerClasses, синтезируемых для отдельных файлов class декомпрессором.

5.8. Схема класса

Цель архива Pack200 состоит в том, чтобы передать ряд классов в форме, которую декомпрессор может позже использовать, чтобы восстановить файлы class. Как правило каждый отдельный вид данных, хранивших в файлах class, передается в полосе, выделенной всем значениям того вида. Вот является структура полосы для всего class специфичной информацией кроме байт-кодов:
  class_bands:
        *class_this :DELTA5 [#class_count] (cp_Class)
        *class_super :DELTA5 [#class_count] (cp_Class)
        *class_interface_count :DELTA5 [#class_count]
        *class_interface :DELTA5 [SUM(*class_interface_count)] (cp_Class)
        *class_field_count :DELTA5 [#class_count]
        *class_method_count :DELTA5 [#class_count]

        *field_descr :DELTA5 [SUM(*class_field_count)] (cp_Descr)
        field_attr_bands

        *method_descr :MDELTA5 [SUM(*class_method_count)] (cp_Descr)
        method_attr_bands

        class_attr_bands
        code_bands
 

class_this, class_super, class_flags_lo, class_flags_hi (если есть), class_interface_count, class_field_count, и полосы class_method_count являются всей длиной #class_count, и соответствующие элементы этих полос передача поочередно имя каждого class и super-class, и число реализованных интерфейсов, объявленных полями, и объявленными методами. (Биты модификатора доступа в слове флагов каждого class смешиваются с индикаторами атрибута, и передаются в class_flags_lo, как определено выше.)

Полоса class_interface содержит выполнения объявлений интерфейса class, один выполненный для каждого элемента class_interface_count, и применения к соответствующему class.

Каждый элемент class_this, class_super, и class_interface является ссылкой (фактически, ненулевой ссылкой) к постоянному пулу cp_Class.

В уникальном случае java/lang/Object сохраненный super-class должен быть нулевой ссылкой. Вместо того, чтобы нарушать передачу всех других элементов полосы class_super, мы используем соглашение, что компрессор, когда это встречается с нулем super-class ссылка, должен передать в ее месте копию ссылки текущего class. (Так как это недопустимо для class, чтобы наследоваться от себя, это изменение нумерации нулевых ссылок однозначно.)

Полосы field_descr содержат одно выполнение элементов для каждого элемента class_field_count, и применяются к последовательным полям в соответствующем class. Полосы method_descr содержат одно выполнение элементов для каждого элемента class_method_count, и применяются к последовательным методам в соответствующем class.

(В отличие от формата файла class, поле и дескрипторы метода сохранены как единственные ссылки на "имя-и-тип" постоянный пул, а не как пары ссылок имени и вводят ссылки.)

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

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

Pack200 архивируют концы с полосами, посвященными блокам кода метода и байт-кодам непосредственно. Если у метода есть атрибут кода, компрессор должен упомянуть это в бите флагов (6-ой LSB), которому это присваивается, или как атрибут переполнения (с индексированием 6). Поля атрибута Кода передаются в полосах, организованных под нетерминальным code_bands.

Спецификация каждого атрибута Кода начинается с трех основных параметров, которые объявляют число стека и локальных слотов, и число обработчиков. #Stack является числом слотов стека, используемых кодом. #NALocal является числом локальных переменных непараметра, используемых кодом. (Фактическим числом локальных переменных, объявленных в файле class, будет #NALocal плюс число локальных переменных, требуемых параметрами метода, как определено подписью метода.) #Handler является числом обработчиков исключений.

Полоса code_headers содержит серию байтов, каждый из которых кратко кодирует первые три основных параметра атрибута кода: Каждое из 255 ненулевых значений байта кодирует уникальный тройной из #NALocal, #Stack, и #Handler. Есть (конечно), один заголовок кода для каждого переданного атрибута Кода.

Специальный нуль (0x00) байта заголовка кода указывает, что атрибут кода три параметра должен быть найден, вместо этого, в code_max_stack, code_max_na_locals, и полосах code_handler_count. Если байт заголовка кода является ненулевым, эти три полосы не передают записи для соответствующего атрибута Кода.

Полоса code_flags_lo передает запись для соответствующего атрибута Code, если и только если один или оба из следующего истина: байт заголовка кода атрибута Кода является нулем, или бит have_all_code_flags устанавливается в слове #archive_options. Если у атрибута Code нет переданного значения code_flags_lo, его слово флагов берется, чтобы быть нулем, и у этого нет никаких податрибутов. Полоса code_flags_hi передает соответствующую запись, если и только если значение code_flags_lo было передано как только описано, и также #have_code_flags_hi устанавливается.

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

Диапазон заголовка #Stack #NALocal #Handler
1 <= x <= 144 (x-1) % 12 (x-1) / 12 0
145 <= x <= 208 (x-145) % 8 (x-145) / 8 1
209 <= x <= 255 (x-209) % 7 (x-209) / 7 2
x = 0 code_max_stack code_max_na_locals code_handler_count
Эта схема позволяет единственному байту описывать атрибут Кода приблизительно в 95 % всех случаев. (Отметьте: Если отладка атрибутов не разделяется, компрессор должен, вероятно, установить бит have_all_code_flags, так, чтобы присутствие этих атрибутов не вызвало использование специального нулевого байта заголовка кода.)

Независимо от того, кодируется ли количество обработчика исключений в однобайтовом заголовке кода, или является ли это явным элементом code_handler_count, для каждого атрибута кода есть выполнение значений в code_handler_start_P, code_handler_end_PO, code_handler_catch_PO, и code_handler_class_RCN, один для каждого обработчика, как будто теми полосами управляло расположение атрибута 'NV[PHPOHPOHRCNH]' (нет никакой полосы, которой управляет элемент расположения 'NV' непосредственно; это - количество обработчика).

Таким образом, каждый триплет Handler.start, Handler.end, и значений Handler.catch передается как перенумеровано (renumber_bci). Кроме того, Handler.end передается как различие его изменения нумерации с тем из Handler.start в том же самом триплете, и Handler.catch передается как различие его изменения нумерации с тем из Handler.end в том же самом триплете. Наконец, code_handler_class_RCN передается как постепенно увеличенная ссылка в cp_Class, или нуль, если обработчик ссылка class является нулем.

  code_bands:
        *code_headers :BYTE1 [COUNT(Code,...)]

        *code_max_stack :UNSIGNED5 [COUNT(0,*code_headers)]
        *code_max_na_locals :UNSIGNED5 [COUNT(0,*code_headers)]

        *code_handler_count :UNSIGNED5 [COUNT(0,*code_headers)]
        *code_handler_start_P :BCI5 [SUM(*code_handler_count)]
        *code_handler_end_PO :BRANCH5 [SUM(*code_handler_count)]
        *code_handler_catch_PO :BRANCH5 [SUM(*code_handler_count)]
        *code_handler_class_RCN :UNSIGNED5 [SUM(*code_handler_count)] (null or cp_Class)

        code_attr_bands
 

5.9. Полосы атрибута

Здесь, собранный в одном месте, полосы, которые передают атрибуты. Если компрессор устанавливает биты в слове флагов class, поля, или метода, и те биты присваиваются (компрессором) к атрибутам, то компрессор должен также получить сохраненные значения, которыми управляет каждое выбранное расположение атрибута, и передать их в полосах, которыми управляет то расположение.

Если компрессор отмечает class (resp. поле, метод, или код) как имеющий атрибуты переполнения, это должно передать соответствующий элемент в полосе class_attr_count (resp. field_attr_count, method_attr_count, или полоса code_attr_count). Это количество, поочередно, определяет размер выполнения в class_attr_indexes (resp. field_attr_indexes, method_attr_indexes, или code_attr_indexes) индексирует разметок атрибута, управляющих атрибутами class (resp. поле, метод, или код). Компрессор должен передать определение расположения атрибута, индексируют для каждого атрибута переполнения.

Для каждого расположения атрибута, выбранного немного в элементе class_flags или элементом class_attr_indexes, компрессор должен получить данные, которыми управляют элементы расположения от атрибута class и элементы передачи, кодирующие эти данные в полосах, которыми управляет расположение. Подобные условия просят поле, метод, и кодируют атрибуты.

Для каждого расположения атрибута, которое передает данные и содержит обратные вызовы, компрессор должен передать число раз, каждый назад вызываемый будет предметом обратного вызова, поскольку декомпрессор прокладывает себе путь посредством разметок атрибута. Эти количества вызова передаются в class_attr_calls, field_attr_calls, method_attr_calls, и полосах code_attr_calls, согласно типу контекста разметок, которым они применяются к. Количества вызова передаются, один на вызываемый обратный, в порядке определения callables. (См. выше.) Количества вызова только передаются для обратных callables, которые происходят в пределах разметок, которые используются, по крайней мере, однажды. Количества вызова не считают записи в любого вызываемыми из-за переводить вызова, и при этом они не считают начальный вызов вызываемого, которое инициирует обработку атрибута. Количество вызова могло бы быть нулем, если обратное вызываемое происходит в расположении, которое используется, но которое, оказывается, не достигает обратного вызываемого. Эти количества вызова необходимы, чтобы повредить зацикливание, свойственное от калибровки полос для взаимно рекурсивных разметок. Они предоставляют минимальную информацию, необходимую для декомпрессора, чтобы определить местоположение всех полос в архиве, до распределения полосы оценивает различным выходным классам. Поэтому количества вызова предоставляются один на расположение, суммированное по всем возникновениям атрибута того каждого расположения.

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

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

Атрибуты под названием "Синтетический", хотя часть стандартного формата файла class в более ранних версиях Java, непосредственно не поддерживаются в этой спецификации, потому что тот атрибут был заменен новым флаговым битом (ACC_SYNTHETIC, 0x1000) в более свежих версиях Java. Однако, компрессоры поощряются обработать Синтетические атрибуты, и любые другие атрибуты нулевые длиной, не предопределенные здесь, присваивая их неиспользованные флаговые биты, и испуская явные определения расположения нулевые длиной для декомпрессоров, чтобы следовать.

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


  class_attr_bands:
        *class_flags_hi :UNSIGNED5 [#class_count*#have_class_flags_hi]
        *class_flags_lo :UNSIGNED5 [#class_count]
        *class_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
        *class_attr_indexes :UNSIGNED5 [SUM(*class_attr_count)]
        *class_attr_calls :UNSIGNED5 [...]
        *class_SourceFile_RUN :UNSIGNED5 [COUNT(SourceFile,...)] (null or cp_Utf8)
        *class_EnclosingMethod_RC :UNSIGNED5 [COUNT(EnclosingMethod,...)] (cp_Class)
        *class_EnclosingMethod_RDN :UNSIGNED5 [COUNT(EnclosingMethod,...)] (null or cp_Descr)
        *class_Signature_RS :UNSIGNED5 [COUNT(Signature,..)] (cp_Signature)
        class_metadata_bands
        ic_local_bands
        *class_file_version_minor_H :UNSIGNED5 [COUNT(version,...)]
        *class_file_version_major_H :UNSIGNED5 [COUNT(version,...)]
        {class_attr_element_bands...}

  field_attr_bands:
        *field_flags_hi :UNSIGNED5 [SUM(*class_field_count)*#have_field_flags_hi]
        *field_flags_lo :UNSIGNED5 [SUM(*class_field_count)]
        *field_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
        *field_attr_indexes :UNSIGNED5 [SUM(*field_attr_count)]
        *field_attr_calls :UNSIGNED5 [...]
        *field_ConstantValue_KQ :UNSIGNED5 [COUNT(ConstantValue,...)] (cp_Int, etc.; see note)
        *field_Signature_RS :UNSIGNED5 [COUNT(Signature,...)] (cp_Signature)
        field_metadata_bands

  method_attr_bands:
        *method_flags_hi :UNSIGNED5 [SUM(*class_method_count)*#have_method_flags_hi]
        *method_flags_lo :UNSIGNED5 [SUM(*class_method_count)]
        *method_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
        *method_attr_indexes :UNSIGNED5 [SUM(*method_attr_count)]
        *method_attr_calls :UNSIGNED5 [...]
        *method_Exceptions_N :UNSIGNED5 [COUNT(Exceptions,...)]
        *method_Exceptions_RC :UNSIGNED5 [SUM(*method_Exceptions_N)] (cp_Class)
        *method_Signature_RS :UNSIGNED5 [COUNT(Signature,...)] (cp_Signature)
        method_metadata_bands
        {method_attr_element_bands...}

  code_attr_bands:
        *code_flags_hi :UNSIGNED5 [...*#have_code_flags_hi]
        *code_flags_lo :UNSIGNED5 [...]
        *code_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
        *code_attr_indexes :UNSIGNED5 [SUM(*code_attr_count)]
        *code_attr_calls :UNSIGNED5 [...]
        *code_StackMapTable_N :UNSIGNED5 [COUNT(StackMapTable,...)]
        *code_StackMapTable_frame_T :BYTE1 [SUM(*code_StackMapTable_N)]
        *code_StackMapTable_local_N :UNSIGNED5 [COUNT(255,*code_StackMapTable_frame_T)]
        *code_StackMapTable_stack_N :UNSIGNED5 [COUNT(255,*code_StackMapTable_frame_T)]
        *code_StackMapTable_offset :UNSIGNED5 [...]
        *code_StackMapTable_T :BYTE1 [...]
        *code_StackMapTable_RC :UNSIGNED5 [COUNT(7,*code_StackMapTable_T)]
        *code_StackMapTable_P :BCI5 [COUNT(8,*code_StackMapTable_T)]
        *code_LineNumberTable_N :UNSIGNED5 [...]
        *code_LineNumberTable_bci_P :BCI5 [...]
        *code_LineNumberTable_line :UNSIGNED5 [...]
        *code_LocalVariableTable_N :UNSIGNED5 [...]
        *code_LocalVariableTable_bci_P :BCI5 [...]
        *code_LocalVariableTable_span_O :BRANCH5 [...]
        *code_LocalVariableTable_name_RU :UNSIGNED5 [...] (cp_Utf8)
        *code_LocalVariableTable_type_RS :UNSIGNED5 [...] (cp_Signature)
        *code_LocalVariableTable_slot :UNSIGNED5 [...]
        *code_LocalVariableTypeTable_N :UNSIGNED5 [...]
        *code_LocalVariableTypeTable_bci_P :BCI5 [...]
        *code_LocalVariableTypeTable_span_O :BRANCH5 [...]
        *code_LocalVariableTypeTable_name_RU :UNSIGNED5 [...] (cp_Utf8)
        *code_LocalVariableTypeTable_type_RS :UNSIGNED5 [...] (cp_Signature)
        *code_LocalVariableTypeTable_slot :UNSIGNED5 [...]
        {code_attr_element_bands...}
 

class обладает "class - псевдоатрибут" версии файла, если вспомогательная или основная версия файла его class отличается от #default_class_minver или #default_class_majver, соответственно. Этот псевдоатрибут является парой 16-разрядных целых чисел, дающих номера основной версии и номера вспомогательной версии файла class. Эти целые числа сохранены в заголовке файла class, а не в записи атрибута. Как соглашение с classfiles, номер вспомогательной версии на первом месте. Таким образом номера вспомогательной версии передаются в полосе class_file_version_minor_H, и номера основной версии в class_file_version_major_H. Декомпрессоры не обязаны обрабатывать архивы с большими номерами вспомогательной версии или номерами основной версии чем таковые из спецификации, которую они были спроектированы, чтобы обработать. Декомпрессоры обязаны обрабатывать архивы с теми же самыми главными и меньшими или равными номерами вспомогательной версии.

Локальные Атрибуты InnerClasses
Переданный class может обладать локальным атрибутом InnerClasses, который берется, чтобы быть корректировкой что в конечном счете записанный атрибут InnerClasses файла class. Определенно, локальный атрибут InnerClasses specifes ряд четырех кортежей, которые должны быть объединены с соответствующим соответствующим подмножеством, оттянутым из ic_All. Алгоритм для того, чтобы сделать это описывается полностью позже, но он составляет запуск с подмножества четырех кортежей от ic_All, которые принадлежат записям CONSTANT_Class вывода постоянный пул (запрещающий записи CONSTANT_Class, требуемые только атрибутом InnerClasses непосредственно), и затем формирующий набор симметричное различие, между которым соответствующий набор и локальный InnerClasses приписывают.

Четыре кортежа всех локальных атрибутов InnerClasses передаются в пяти полосах:

  ic_local_bands:
        *class_InnerClasses_N :UNSIGNED5 [COUNT(InnerClasses,...)]
        *class_InnerClasses_RC :UNSIGNED5 [SUM(*class_InnerClasses_N)] (cp_Class)
        *class_InnerClasses_F :UNSIGNED5 [SUM(*class_InnerClasses_N)]
        *class_InnerClasses_outer_RCN :UNSIGNED5 [COUNT(!=0,*class_InnerClasses_F)]  (null or cp_Class)
        *class_InnerClasses_name_RUN :UNSIGNED5 [COUNT(!=0,*class_InnerClasses_F)] (null or cp_Utf8)
 

Каждый <C,F,C2,N> с четырьмя кортежами, переданный в этих полосах атрибута, вызывают локальным кортежем IC. (Отметьте, что формат файла class хранит элементы этих четырех кортежей в различном порядке, (C,C2,N,F).) Для данного файла X class последовательность локальных кортежей IC вызывают ic_Local(X).

Для каждого локального кортежа IC, передач компрессора, в минимуме, значении C и значении F. Если переданное значение флагов F не является нулем, есть также соответствующие переданные постоянные ссылки пула C2 и N. В целом переданный локальный кортеж может или, возможно, не эквивалентен глобальному кортежу от ic_All.

Как сокращение, компрессор может передать только C и значение флагов нуля, если локальный кортеж IC, который будет передан, эквивалентен элементу ic_All, и никакой другой элемент ic_All не определяет тот же самый class C. В этом случае декомпрессор должен вести себя точно, как будто все четыре компонента кортежа были явно переданы.

(Если все четыре компонента локального кортежа передаются, и значение флагов, которое будет передано, является фактически нулем, значение, 0x00010000 должен быть передан вместо нуля для флагов.)

Часто, компрессор не должен будет передать локальные кортежи IC вообще, так как набором четырех кортежей, которые будут сохранены в атрибуте InnerClasses class, будет точно ic_Relevant(X) без требуемой корректировки. Если посторонние четыре кортежа (вне требуемых минимизированным постоянным пулом) будут сочтены во вводе файлом class, то некоторые локальные кортежи IC будут необходимы (с нулевыми флагами), чтобы обеспечить локальные "корни" для дополнительных записей InnerClasses. Это может произойти, если компилятор требует записи InnerClasses для class, упомянутого только в подписи. Компрессоры обязаны предсказывать, какие классы требуют таких дополнительных локальных корней, и передают только неожиданные четыре кортежа.

5.9.1. Передача метаданных
Есть девять групп полос, которыми управляют разметки метаданных. Они получаются в итоге здесь.
  class_metadata_bands:
        class_RVA_bands
        class_RIA_bands

  field_metadata_bands:
        field_RVA_bands
        field_RIA_bands

  method_metadata_bands:
        method_RVA_bands
        method_RIA_bands
        method_RVPA_bands
        method_RIPA_bands
        method_AD_bands

  class_RVA_bands:
        *class_RVA_anno_N :UNSIGNED5 [...] 
        *class_RVA_type_RS :UNSIGNED5 [...] (cp_Signature)
        *class_RVA_pair_N :UNSIGNED5 [...] 
        *class_RVA_name_RU :UNSIGNED5 [...] (cp_Utf8)
        *class_RVA_T :BYTE1 [...] 
        *class_RVA_caseI_KI :UNSIGNED5 [...] (cp_Int)
        *class_RVA_caseD_KD :UNSIGNED5 [...] (cp_Double)
        *class_RVA_caseF_KF :UNSIGNED5 [...] (cp_Float)
        *class_RVA_caseJ_KJ :UNSIGNED5 [...] (cp_Long)
        *class_RVA_casec_RS :UNSIGNED5 [...] (cp_Signature)
        *class_RVA_caseet_RS :UNSIGNED5 [...] (cp_Signature)
        *class_RVA_caseec_RU :UNSIGNED5 [...] (cp_Utf8)
        *class_RVA_cases_RU :UNSIGNED5 [...] (cp_Utf8)
        *class_RVA_casearray_N :UNSIGNED5 [...] 
        *class_RVA_nesttype_RS :UNSIGNED5 [...] (cp_Signature)
        *class_RVA_nestpair_N :UNSIGNED5 [...] 
        *class_RVA_nestname_RU :UNSIGNED5 [...] (cp_Utf8)

  class_RIA_bands:
        *class_RIA_anno_N :UNSIGNED5 [...] 
        (analogous to class_RVA_bands)

  field_RVA_bands:
        *field_RVA_anno_N :UNSIGNED5 [...] 
        (analogous to class_RVA_bands)

  field_RIA_bands:
        *field_RIA_anno_N :UNSIGNED5 [...] 
        (analogous to field_RVA_bands)

  method_RVA_bands:
        *method_RVA_anno_N :UNSIGNED5 [...] 
        (analogous to class_RVA_bands)

  method_RIA_bands:
        *method_RIA_anno_N :UNSIGNED5 [...] 
        (analogous to method_RIA_bands)

  method_RVPA_bands:
        *method_RVPA_param_NB :BYTE1 [...] 
        *method_RVPA_anno_N :UNSIGNED5 [...] 
        (analogous to method_RVA_bands)

  method_RIPA_bands:
        *method_RIPA_param_NB :BYTE1 [...] 
        *method_RIPA_anno_N :UNSIGNED5 [...] 
        (analogous to method_RVPA_bands)

  method_AD_bands
        *method_AD_T :BYTE1 [...] 
        *method_AD_caseI_KI :UNSIGNED5 [...] (cp_Int)
        *method_AD_caseD_KD :UNSIGNED5 [...] (cp_Double)
        *method_AD_caseF_KF :UNSIGNED5 [...] (cp_Float)
        *method_AD_caseJ_KJ :UNSIGNED5 [...] (cp_Long)
        *method_AD_casec_RS :UNSIGNED5 [...] (cp_Signature)
        *method_AD_caseet_RS :UNSIGNED5 [...] (cp_Signature)
        *method_AD_caseec_RU :UNSIGNED5 [...] (cp_Utf8)
        *method_AD_cases_RU :UNSIGNED5 [...] (cp_Utf8)
        *method_AD_casearray_N :UNSIGNED5 [...] 
        *method_AD_nesttype_RS :UNSIGNED5 [...] (cp_Signature)
        *method_AD_nestpair_N :UNSIGNED5 [...] 
        *method_AD_nestname_RU :UNSIGNED5 [...] (cp_Utf8)

Как средство пониманию расположения метаданных, вот краткое описание каждой из полос метаданных метода, как использующийся classfiles, которые выполняют JSR 175. class и полевые полосы метаданных функционируют похожим способом.

Отметьте, что JSR 175 не позволяет встроенные ссылки на записи CONSTANT_Class, даже там, где ссылка на class требуется. Вместо этого JSR 175 требует, чтобы ссылки на классы были закодированы как полевые подписи. (Их имена заключаются в скобки 'L' и';'.) Архив Pack200 передает все такие значения как ссылки в cp_Signature, не cp_Class.

Для каждого использования атрибута аннотации параметра, полосы method_RVPA_param_NB или полосы method_RIPA_param_NB (для невидимых аннотаций) передает байт без знака, указывающий на количество параметра. Для каждого использования атрибута аннотации непараметра, полосы method_RVA_anno_N или полосы method_RIA_anno_N (для невидимых аннотаций) передает количество аннотации. Аналогично, для каждого аннотируемого параметра, полосы method_RVPA_anno_N или полосы method_RIPA_anno_N (для невидимых аннотаций) передает количество аннотации.

Для каждой видимой аннотации непараметра полоса method_RVA_type_RS передает тип аннотации, и полоса method_RVA_pair_N передает число который пары задействованного значения аннотации. Аналогичные значения для невидимых аннотаций и аннотаций параметра передаются в полосах method_RIA_type_RS, method_RIA_pair_N, method_RVPA_type_RS, method_RVPA_pair_N, method_RIPA_type_RS, и method_RIPA_pair_N. Для каждой пары задействованного значения, переданной как прямая часть видимой аннотации непараметра, полоса method_RVA_name_RU передает имя элемента. Аналогичные значения для невидимых аннотаций и аннотаций параметра передаются в полосах method_RIA_name_RU, method_RVPA_name_RU, и method_RIPA_name_RU.

Для каждого значения, переданного с видимой аннотацией непараметра, передает ли непосредственно, или косвенно через вложенное значение или аннотацию, полоса method_RVA_T байт, который выбирает формат значения аннотации, и аналогичных значений, передаются в полосах method_RIA_T, method_RVPA_T, method_RIPA_T, и (для значений по умолчанию аннотации) method_AD_T, Прямое использование этих полос тега значения считается, суммируя значения соответствующей предыдущей полосы парного количества (method_RVA_pair_N, и т.д.). Это количество также включает сумму соответствующей следующей вложенной полосы парного количества (method_RVA_nestpair_N, и т.д.) и вложенных полос длины массива (method_RVA_casearray_N, и т.д.).

Начиная с тех последних сумм, прибывших от обратных вызовов в расположение атрибута, они не могут быть непосредственно вычислены декомпрессором, но об их сумме сообщает компрессор как элемент method_attr_calls. (Отметьте, что последней вызываемой в каждом расположении метаданных является цель двух обратных вызовов изнутри себя.), Что полоса содержит, они назад вызывают счета для method_RVA_T, method_RIA_T method_RVPA_T, method_RIPA_T method_AD_T, в том порядке. Если нет никаких возникновений атрибута метаданных метода, то соответствующий обратный вызов опускается. (Таким образом есть до пяти обратных количеств вызова, переданных для метаданных метода.), Если там определяются с помощью компрессора рекурсивные разметки, используемые в архиве, их обратные количества вызова следуют за счетами для метаданных в method_attr_calls.

Для каждого тега значения 'B', 'C', 'я', 'S', или 'Z', есть соответствующий элемент, переданный в method_RVA_caseI_KI, который предоставляет значение как cp_Int ссылку. Аналогичные целочисленные ссылки в пределах невидимого и аннотаций параметра и значений по умолчанию аннотации передаются в полосах method_RIA_caseI_KI, method_RVPA_caseI_KI, method_RIPA_caseI_KI, и method_AD_caseI_KI. Для каждого тега значения 'e' полосы method_RVA_caseet_RS и method_RVA_caseec_RU передают подпись class и имя элемента постоянного перечисления как ссылки в cp_Signature и cp_Utf8. Для каждого тега значения '[', полоса method_RVA_casearray_N передает длину вложенного массива значения. Для каждого тега значения, полосы method_RVA_nesttype_RS и method_RVA_nestpair_N передают class signtaure вложенной аннотации и числа ее пар. Для каждой пары в такой вложенной аннотации полоса method_RVA_nestname_RU передает имя пары.

Полосы в следующей таблице передают ссылки пула соответственно-типизированной-константы для каждого происшествия определенных символов тега.

Тег (и) Полоса Ссылка
'B','C','I','S','Z' method_RVA_caseI_KI cp_Int
'D' method_RVA_caseD_KD cp_Double
'F' method_RVA_caseF_KF cp_Float
'J' method_RVA_caseJ_KJ cp_Long
'c' method_RVA_casec_RS cp_Signature
'e' method_RVA_caseet_RS
method_RVA_caseec_RU
cp_Signature
cp_Utf8
's' method_RVA_cases_RU cp_Utf8

Аналогичные группы полос передают значения в пределах других четырех типов аннотации метода, и в пределах видимых и невидимых аннотаций классов и полей.

5.10. Инструкции байт-кода

Последняя часть архива Pack200 является серией полос, передающих байт-коды непосредственно. Байт-коды каждого кода метода анализируются в инструкции и операнды, переданные в их собственных полосах. Каждый код метода соответствует выполнению байт-кодов, которое заканчивается выдающимся кодовым обозначением 0xFF (255), который служит маркером конца. (Отметьте, что для данных полосы необычно быть разграниченным маркером конца: Обычно это измеряется количеством в предыдущей полосе.)

Вот полосы, которые передают инструкции байт-кода:

  bc_bands:
        *bc_codes :BYTE1 [...]
        *bc_case_count :UNSIGNED5 [COUNT(switch,*bc_codes)]
        *bc_case_value :DELTA5 [...]
        *bc_byte :BYTE1 [...]
        *bc_short :DELTA5 [...]
        *bc_local :UNSIGNED5 [...]
        *bc_label :BRANCH5 [...]
        *bc_intref :DELTA5 [...] (cp_Int)
        *bc_floatref :DELTA5 [...] (cp_Float)
        *bc_longref :DELTA5 [...] (cp_Long)
        *bc_doubleref :DELTA5 [...] (cp_Double)
        *bc_stringref :DELTA5 [...] (cp_String)
        *bc_loadablevalueref :DELTA5 [...] (cp_LoadableValue)
        *bc_classref :UNSIGNED5 [...] (current class or cp_Class)
        *bc_fieldref :DELTA5 [...] (cp_Field)
        *bc_methodref :UNSIGNED5 [...] (cp_Method)
        *bc_imethodref :DELTA5 [...] (cp_Imethod)
        *bc_indyref :DELTA5 [...] (cp_InvokeDynamic)
        *bc_thisfield :UNSIGNED5 [...] (cp_Field, only for current class)
        *bc_superfield :UNSIGNED5 [...] (cp_Field, only for current super)
        *bc_thismethod :UNSIGNED5 [...] (cp_Method, only for current class)
        *bc_supermethod :UNSIGNED5 [...] (cp_Method, only for current super)
        *bc_initref :UNSIGNED5 [...] (cp_Field, only for most recent new)
        *bc_escref :UNSIGNED5 [COUNT(ref_escape,*bc_codes)] (cp_All)
        *bc_escrefsize :UNSIGNED5 [...]
        *bc_escsize :UNSIGNED5 [...]
        *bc_escbyte :BYTE1 [...]
 

Чтобы передать инструкции байт-кода более эффективно, некоторые инструкции могут быть переписаны в форму передачи. ldc, ldc_w, и ldc2_w байт-коды должен быть переписан компрессором в операции со строгим контролем типов; см. ниже. Некоторый getstatic, putstatic, getfield, putfield, invokevirtual, invokespecial, и invokestatic байт-коды могут (в опции компрессора) быть переписанными в более специализированные и компактные формы, которые, потому что они контекстно-зависимы, выбирают их операнды из меньшего набора возможностей.

Во всех случаях первый байт каждой инструкции (возможно, переписанный) определяется байтом, переданным в bc_codes. Все байты операнда декодируются в операнды и передаются в отдельных полосах согласно типу закодированного операнда. Дополнительные байты инструкций переключателя и последние два байта invokeinterface инструкций отбрасываются, потому что они могут быть восстановлены декомпрессором.

"Широкий" префиксный байт-код передается в bc_codes. Инструкция после префикса декодируется в его широком формате, но (кроме в случае iinc) это передается таким же образом, и использование тех же самых полос, как нормальный (неширокий) формат. Широкий формат iinc инструкции использует bc_short вместо bc_byte, чтобы передать его второй операнд.

Каждая команда перехода передает свою цель (или цели, в случае переключателей) в полосе bc_label, закодированной как различие между перенумерованным BCI цели ответвления и перенумерованным BCI ответвления непосредственно. (Изменение нумерации, столь же описанное выше, нумерует первую инструкцию как нуль, второе как один, и т.д.) Различия между перенумерованными BCI очень компактны; основное кодирование BRANCH5 также использует в своих интересах факт, что большинство таких различий положительно, потому что большинство ответвлений является прямыми ответвлениями.

Постепенно увеличенные переносы полосы bc_classref индексируют в cp_Class постоянный пул. Постепенное увеличение (единицей) резервирует нуль кода, который всегда обращается к текущему class. (Это обеспечивает компактную форму для наиболее распространенной ссылки class, которая является самоссылкой.)

bc_byte и фиксированный перенос полос bc_short - измеренные операнды. Эти операнды не передаются как общие 32-разрядные целые числа, потому что их инструкции, как первоначально определено, уже служат особенно сжатыми форматами передачи. Целочисленные значения этих полос обрабатываются как без знака, даже когда они семантически подписываются как операнды. Полоса bc_byte используется для последних операндов multianewarray и нешироких iinc инструкций, и для операндов bipush и newarray инструкций. Полоса bc_short используется для последних операндов широких iinc инструкций, и для операндов sipush инструкций.

Полосы bc_intref, bc_floatref, bc_longref, bc_doubleref, bc_stringref, bc_fieldref, bc_methodref, и bc_imethodref передают показатели преломления обыкновенной волны в постоянные пулы cp_Int, cp_Float, cp_Long, cp_Double, cp_String, cp_Field, cp_Method, и cp_Imethod, соответственно.

Полоса передачи bc_indyref индексирует в cp_InvokeDynamic для инструкций invokedynamic.

Полоса передачи bc_loadablevalueref индексируют в постоянную группу пула cp_LoadableValue, так, что нуль, обращается к первой константе CONSTANT_Integer и так далее. Это сразу передается после bc_stringref. (Как правило, эта полоса используется для констант cp_MethodHandle.)

(Инструкции invokedynamic могут только появиться, когда #archive_majver 170 или выше. Они и их связанные постоянные типы пула были представлены в недавних версиях формата classfile.)

Для каждого lookupswitch или tableswitch инструкции, число случаев передается в bc_case_count, и метка значения по умолчанию передается в bc_label. Каждое значение случая и цель случая lookupswitch передаются в bc_case_value и bc_label, соответственно. Начальное значение случая tableswitch передается в bc_case_value, и каждая из его целей случая передается в bc_label.

Если у первого байта инструкции есть код в диапазоне [202.. 255], или если операнды инструкции не могут быть проанализированы согласно требованиям этой спецификации, это - нестандартная инструкция. Каждый байт нестандартной инструкции должен быть передан в специальном конверте, чтобы попросить декомпрессор принять это буквально. Конверт состоит из серии "byte_escape" и "ref_escape" кодов операций в полосе bc_code, соответствующих размеров в bc_escsize и bc_escrefsize, байтах в bc_escbyte, и постоянных ссылках пула в bc_escref. Каждой постоянной ссылки пула в нестандартной инструкции нужно оставить и передана в полосе bc_escref. Каждый ref_escape обертывает одну такую постоянную ссылку пула размера до четырех байтов. Переданная ссылка является индексированием в cp_All, так, что обнулите, обращается к первой константе CONSTANT_Utf8, и так далее.

Escape
Код операции
Размер
Операнд
Операнд
Размер
Размер
Полоса
Данные
Полоса
Код операции
Значение
byte_escape N <=255 N байты bc_escsize bc_escbyte 254
ref_escape N <=2 N байты bc_escrefsize bc_escref 253

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

Вот таблица особенно переписанных форм передачи для инструкций:

я
Исходный
Инструкция
Операнд Передача
Инструкция
Перезапись
Необходимый?
Код операции
ldc cp_String [я] sldc да 18 (=ldc)
ldc cp_Class [я] cldc да 233
ldc cp_Int [я] ildc да 234
ldc cp_Float [я] fldc да 235
ldc_w cp_String [я] sldc_w да 19 (=ldc_w)
ldc_w cp_Class [я] cldc_w да 236
ldc_w cp_Int [я] ildc_w да 237
ldc_w cp_Float [я] fldc_w да 238
ldc2_w cp_Long [я] lldc2_w да 20 (=ldc2_w)
ldc2_w cp_Double [я] dldc2_w да 239
ldc cp_LoadableValue [я] qldc да 240
ldc_w cp_LoadableValue [я] qldc_w да 241
getstatic (этот элемент class) getstatic_this нет 202
putstatic (этот элемент class) putstatic_this нет 203
getfield (этот элемент class) getfield_this нет 204
putfield (этот элемент class) putfield_this нет 205
invokevirtual (этот элемент class) invokevirtual_this нет 206
invokespecial (этот элемент class) invokespecial_this нет 207
invokestatic (этот элемент class) invokestatic_this нет 208
aload_0; getstatic (этот элемент class) aload_0_getstatic_this нет 209
aload_0; putstatic (этот элемент class) aload_0_putstatic_this нет 210
aload_0; getfield (этот элемент class) aload_0_getfield_this нет 211
aload_0; putfield (этот элемент class) aload_0_putfield_this нет 212
aload_0; invokevirtual (этот элемент class) aload_0_invokevirtual_this нет 213
aload_0; invokespecial (этот элемент class) aload_0_invokespecial_this нет 214
aload_0; invokestatic (этот элемент class) aload_0_invokestatic_this нет 215
getstatic (элемент class высшего качества) getstatic_super нет 216
putstatic (элемент class высшего качества) putstatic_super нет 217
getfield (элемент class высшего качества) getfield_super нет 218
putfield (элемент class высшего качества) putfield_super нет 219
invokevirtual (элемент class высшего качества) invokevirtual_super нет 220
invokespecial (элемент class высшего качества) invokespecial_super нет 221
invokestatic (элемент class высшего качества) invokestatic_super нет 222
aload_0; getstatic (элемент class высшего качества) aload_0_getstatic_super нет 223
aload_0; putstatic (элемент class высшего качества) aload_0_putstatic_super нет 224
aload_0; getfield (элемент class высшего качества) aload_0_getfield_super нет 225
aload_0; putfield (элемент class высшего качества) aload_0_putfield_super нет 226
aload_0; invokevirtual (элемент class высшего качества) aload_0_invokevirtual_super нет 227
aload_0; invokespecial (элемент class высшего качества) aload_0_invokespecial_super нет 228
aload_0; invokestatic (элемент class высшего качества) aload_0_invokestatic_super нет 229
invokespecial (этот class <init>) invokespecial_this_init нет 230
invokespecial (class высшего качества <init>) invokespecial_super_init нет 231
invokespecial (новый class <init>) invokespecial_new_init нет 232

Использование инструкций qldc И qldc_w индексирует в постоянную группу пула cp_LoadableValue, чтобы выбрать произвольные загружаемые константы. (Эти инструкции могут только появиться, когда #archive_majver 170 или выше. Ранние версии формата classfile не требуют их.) Декомпрессоры обязаны принимать любую постоянную ссылку как операнд к одной из этих инструкций, но компрессоры поощряются передать только константы, которые не могут быть закодированы другими разновидностями ldc, определенно элементы cp_MethodHandle и cp_MethodType.

(Отметьте: предыдущая версия этой спецификации, упомянутой переносящие строку разновидности ldc, sldc и sldc_w, как aldc и aldc_w. Несмотря на новые имена, кодовые точки и их интерпретация не изменились. Старые названия осуждаются.)

Каждая инструкция байт-кода содержится class, названным текущим class. Суперклассом (если кто-либо) текущего class является текущий class высшего качества. Операнд дословно новой "новой" инструкции (в том же самом методе) вызывают текущим новым class.

Если инструкция обращается к полю или методу в текущем class, это может (в опции компрессора), переписываются для передачи как соответствующий код операции, записанный с "_this". Аналогично, инструкция, обращающаяся к полю или методу в текущем class высшего качества, может быть переписана как соответствующий код операции, записанный с "_super". В любом случае, если сразу предыдущая инструкция является aload_0 (код операции 42), передача той инструкции может быть подавлена компрессором, и соответствующим кодом операции, записанным с "aload_0 _" выбранный вместо этого; иначе "aload_0 _" разновидность не может быть выбрана.

Если invokespecial инструкция обращается к методу, названному <init> в текущем class, текущем class высшего качества, или текущем новом class, компрессор может хотеть переписывать это как invokespecial_this_init, invokespecial_super_init, или invokespecial_new_init, соответственно.

Поле (resp. метод) операнды переписанных инструкций, записанных с "_this" (но не "_init"), передается в специальной полосе bc_thisfield (resp. bc_thismethod). Нумерация этих операндов определяется, беря последовательность символов в cp_Field (resp. cp_Method) и выбор только элементы текущего class. Получающееся подмножество, не изменяя его порядок, перенумеровывается, запускаясь с нуля. Это обеспечивает компактное отображение маленьких целых чисел к элементам текущего class.

Аналогично, операнды переписанных инструкций, записанных с "_super" (но не "_init"), передаются в bc_superfield или полосе bc_supermethod, и перенумеровываются как подмножество cp_Field или cp_Method, выбирая только элементы текущего class высшего качества.

Наконец, операнды переписанных инструкций, записанных с "_init", передаются в полосе bc_initref, и перенумеровываются как подмножество cp_Method, выбрали согласно соответствующему class (ток, ток супер, или новый ток), и также выбрали, чтобы иметь имя <init>. (Индексирование переданного является обычно очень маленьким; в действительности это выбирает только подпись вызванного метода, и большинство классов обладает только несколькими конструкторами.)

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

Инструкция Операнд Переданный
Значение
Полоса
bipush (байт) x x & 0xFF bc_byte
sipush (короткий) x x & 0xFFFF bc_short
ildc cp_Int [я] я bc_intref
fldc cp_Float [я] я bc_floatref
sldc cp_String [я] я bc_stringref
qldc cp_LoadableValue [я] я bc_loadablevalueref
cldc текущий class 0 bc_classref
cldc cp_Class [я] i+1 bc_classref
ildc_w cp_Int [я] я bc_intref
fldc_w cp_Float [я] я bc_floatref
sldc_w cp_String [я] я bc_stringref
qldc_w cp_LoadableValue [я] я bc_loadablevalueref
cldc_w текущий class 0 bc_classref
cldc_w cp_Class [я] i+1 bc_classref
lldc2_w cp_Long [я] я bc_long
dldc2_w cp_Double [я] я bc_double
*load локальные переменные [я] я bc_local
*store локальные переменные [я] я bc_local
мочить локальные переменные [я] я bc_local
iinc локальные переменные [я] я bc_local
iinc (не широкий) (байт) x x & 0xFF bc_byte
 (широкий) iinc (короткий) x x & 0xFFFF bc_short
если ** pc (дельта/перенумеровывать) bc_label
if_ ** pc (дельта/перенумеровывать) bc_label
goto pc (дельта/перенумеровывать) bc_label
jsr pc (дельта/перенумеровывать) bc_label
goto_w pc (дельта/перенумеровывать) bc_label
jsr_w pc (дельта/перенумеровывать) bc_label
tableswitch  количество случая количество bc_case_count
tableswitch  pc значения по умолчанию (дельта/перенумеровывать) bc_label
tableswitch первое  значение случая значение bc_case_value
tableswitch каждый  pc случая (дельта/перенумеровывать) bc_label
lookupswitch  количество случая количество bc_case_count
lookupswitch  pc значения по умолчанию (дельта/перенумеровывать) bc_label
lookupswitch каждое  значение случая значение bc_case_value
lookupswitch каждый  pc случая (дельта/перенумеровывать) bc_label
новый текущий class 0 bc_classref
новый cp_Class [я] 1+i bc_classref
newarray введите код значение bc_byte
anewarray текущий class 0 bc_classref
anewarray cp_Class [я] 1+i bc_classref
checkcast текущий class 0 bc_classref
checkcast cp_Class [я] 1+i bc_classref
instanceof текущий class 0 bc_classref
instanceof cp_Class [я] 1+i bc_classref
multianewarray cp_Class [я] 1+i bc_classref
multianewarray разряд разряд & 0xFF bc_byte
getstatic cp_Field [я] я bc_fieldref
putstatic cp_Field [я] я bc_fieldref
getfield cp_Field [я] я bc_fieldref
putfield cp_Field [я] я bc_fieldref
invokevirtual cp_Method [я] я bc_methodref
invokespecial cp_Method [я] я bc_methodref
invokestatic cp_Method [я] я bc_methodref
invokeinterface cp_Imethod [я] я bc_imethodref
invokedynamic cp_InvokeDynamic [я] я bc_indyref
** _this this_fields [я] я bc_thisfield
** _this this_methods [я] я bc_thismethod
** _super super_fields [я] я bc_superfield
** _super super_methods [я] я bc_supermethod
invokespecial_this_init this_constructors [я] я bc_initref
invokespecial_super_init super_constructors [я] я bc_initref
invokespecial_new_init new_constructors [я] я bc_initref

6. Спецификация Кодирования Полосы

Полоса Pack200 состоит из последовательности маленьких целых чисел, каждое из которых является представимым в 32 битах. В зависимости от намеченного использования этих чисел они могут быть интерпретированы, чтобы обладать знаком дополнения пар.

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

(Отметьте: В этой учетной записи кодировок байты являются неделимыми октетами, которые выражают значения без знака в [0,255].)

6.1. Кодирование Маленьких Целых чисел

Есть маленький, но гибкий набор возможных кодировок, позволенных архивом. Они все основаны на схеме с двумя параметрами codings для небольших целых без знака, который далее параметризован опциями для представления знака и кодирования дельты, и специальными режимами для медленно переменных кодировок, и для компактного переименования частых значений.

6.1.1. Схема Многократного Codings

Кодирование маленького целого числа зависит от двух независимых параметров B и H, и полученного параметра L:
Имя Диапазон Значение
B [1..5] максимальная длина байта
H [1..256] число высоких значений байта
L [0..255] число значений младшего байта, определенных как (256-ой)

Учитывая любые два значения B и H, есть кодирование (B, H), который устанавливает взаимно-однозначное соответствие между начальной последовательностью неотрицательных целых чисел, и "кодирование устанавливает" коротких последовательностей байтов.

Кроме того никакая последовательность байта в наборе кодирования не является надлежащим префиксом другой последовательности байта в том же самом наборе. префикс. Это означает, неофициально, что кодировки самоизмеряют, или "parseable".

Кроме того, набор кодирования настолько полон насколько возможно, так, чтобы каждый достаточно долго последовательность байтов началась с уникального префикса байтов, оттянутых из набора кодирования. В частности у каждой последовательности байтов B есть (уникальный) префикс в наборе кодирования для (B, H) кодирование.

6.1.2. Определение Кодирования Последовательностей Байта

Относительно данного (B, H) кодирование, мы говорим, что байт "высок", если его значение находится в диапазоне [256-H..255]. Мы также говорим, что байт "низок", если L положителен, и значение байта находится в диапазоне [0..L-1]

Данный (B, H) кодирование, последовательность байтов находится в ее наборе кодирования, если и только если все следующее является истиной:

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

  encoding_set = (high* low) | (high)^B

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

Если n является меньше чем B тогда число (B, H), кодировками длины точно n является (H^(n-1) * L). Числом (B, H) кодировки длины точно B является (H^(B-1) * (L+H)). Сумма этих значений для всего n в [1..B] является полным размером набора кодирования для (B, H) кодирование. Это вызывают Картой (B, H) и поэтому определяется как:

  Card(B,H) = (L * (1-H^B)/(1-H)) + H^B
    if H>1, or else
  Card(B,1) = B*255+1
 

Если H 256, нет никаких младших байтов, и набор кодирования состоит из всех возможных последовательностей точно B байты, и Картой (B, H) является 256^B.

Иначе, набор кодирования состоит из последовательностей различных длин, от 1 до B включительно. В частности есть однобайтовые последовательности L. Мы будем использовать их в другом месте, чтобы закодировать "привилегированные" целые числа самой высокой частоты. Отметьте, что правила кодирования, определенные в другом месте в этом документе, разрабатываются, чтобы производить меньшие целые числа более часто чем большие.

Отметьте, что L может быть просмотрен как параметр "резкости", выражая резкость распределения о нуле математических ожиданий, которые будут закодированы. Чем больший L, тем больше кодирование одобряет дистрибутивы значений, которые являются близко к нулю, и редко отнюдь нет. Больший H оценивает пользу "более плоские" дистрибутивы, до H=256, L=0, который благоприятно кодирует абсолютно случайные данные в пределах диапазона кодирования.

6.1.3. Определение Декодируемых Значений Целого числа

Диапазон (B, H) кодирование является целыми числами в [0..Card(B,H)-1]. (Отметьте, что этот диапазон применяется только к codings без знака, представляемому до сих пор в этом разделе.)

Учитывая последовательность байта N оценивает b [0].. b [N-1], основанное на сортировке определение, данное выше, подразумевает, что декодируемое целочисленное значение этой последовательности байта является основой-H с прямым порядком байтов масштабируемая сумма байтов, и вызывается, Декодируют (B, H; b):

  Decode(B,H; b[*]) = Sum[0<=i<N]( b[i] * H^i )
 

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

Отметьте, что нуль числа всегда кодируется последовательностью нулевых байтов B (если H 256), или иначе единственным нулевым байтом.

Самое большое закодированное арифметическое значение всегда кодируется последовательностью байтов B 255 имеющие значение.

Отметьте, что (B, H) кодировки (1 256), (2 256), и (4 256) идентичны со стандартными представлениями с прямым порядком байтов байтов без знака, 16-разрядных целых чисел без знака, и 32-разрядных целых чисел без знака.

Отметьте, что некоторые могут представить арифметические значения, больше чем 2^31-1 или даже 2^32-1. Это - функция (B, H) кодирование схемы. (Но иногда промежуточные 64-разрядные значения требуются, когда многократные знаковые биты используются, как описано ниже. Правила, данные ниже для подписанных значений, требуют, чтобы компрессор испустил самое простое кодирование, которое будет достаточно, чтобы передать необходимое 32-разрядное целое число, даже если более сложные последовательности произвели бы то же самое 32-разрядное значение после усечения.)

Отметьте, что реализации не всегда свободны усечь промежуточные значения, вычисляя (B, H) кодирующие значения. Однако, финал декодируемые значения (после восстановления знаков) будет всегда помещаться в 32 бита, как описано в следующем разделе.

6.2. Кодирование Целых чисел со знаком

Чтобы закодировать подписанные 32-разрядные числа, мы добавляем другой параметр к (B, H) кодирование схемы.
Имя Диапазон Значение
B [1..5] максимальная длина байта
H [1..256] число высоких значений байта
L [0..255] число значений младшего байта, определенных как (256-ой)
S [0..2] число знаковых битов

Целое число U полученный из (B, H) кодирование преобразовывается в подписанное 32-разрядное значение X способом, который зависит от параметра S. Этот процесс вызывают преобразованием знака.

Неофициально, преобразование знака выполняется 32-разрядным усечением если S=0. Иначе, биты младшего разряда U все вместе обрабатываются как знаковый бит, так, чтобы X было отрицательно, только если все знаковые биты устанавливаются. Эти два преобразования от U до положительного X и U к отрицательному X являются независимо плотными и монотонными в противоположных направлениях, как определено ниже.

В отличие от этого (B, H) кодирование, (B, H, S) кодирование представляет только числа в определенно определенном диапазоне, который никогда не больше чем [-2^31..2^31-1].

В дальнейшем, для каждого (B, H, S) кодирование, мы определяем Диапазон (B, H, S), и метод, используемый, чтобы представить 32-разрядные подписанные значения с тем кодированием.

(B, H) кодирование последовательности байта не является юридическим вводом к соответствию (B, H, S) кодирование, если это представляет целое число U, который не преобразовывает в диапазон (B, H, S) кодирование. Кроме того, если есть двухбайтовые последовательности, кодирующие значения U1 и U2, который обе карты в ту же самую точку X в подписанном диапазоне, только последовательность байта для меньшего из U1 и U2 является законной.

Таким образом, (B, H, S) у кодирования может быть меньшее количество элементов чем соответствие (B, H) кодирование, из-за недопустимых последовательностей байта кодирования.

Диапазон (B, H, S) кодирование содержит все 32-разрядные целые числа со знаком [-2^31..2^31-1], если Картой (B, H) является 2^32 или больше. (Отрицательные величины представляются 31-разрядным переполнением без знака.), Если кодирование кодирует меньше значений без знака, вершина его диапазона отсекается к 2^31-1, и нижняя часть его диапазона отсекается к -2^31.

Более точно, диапазон (B, H, S) кодирование вызывают Диапазоном (B, H, S) и определяется (частично для S=0) как:

  Range(B,H,S) = [-2^31..2^31-1]
    if S=0, Card(B,H) >= 2^32, or
  Range(B,H,S) = [0..2^31-1]
    if S=0, 2^31 < Card(B,H) < 2^32, or else
  Range(B,H,S) = [0..Card(B,H)-1]
    if S=0, Card(B,H) <= 2^31
 
Компрессору не позволяют испустить последовательность байта, которая, когда интерпретирующийся согласно текущему кодированию, декодирует к значению за пределами диапазона того кодирования.

(Отметьте, что декомпрессоры могут произвести произвольные ответы для codings из диапазона, так как компрессорам не позволяют испустить их. Это позволяет декомпрессорам использовать 32-разрядную арифметику для большинства вычислений, игнорируя возможность нежелательного wraparond.)

Если S> 0, декодирование последовательности байта выполняется сначала, декодируя это как (B, H) кодирование, и затем преобразовывая декодируемое целое число в подписанное 32-разрядное число. Это преобразование знака зависит только от арифметического значения U полученный из (B, H) кодирование, и на значении S. Арифметическое значение должно быть сохранено вне 32 битов точности, если преобразование знака произведет значение в пределах диапазона кодирования. Если количество элементов (B, H) кодированием является 2^32 или больше, (B, H, S), кодирование производит все возможные подписанные 32-разрядные отрицательные величины 32-разрядным усечением промежуточного целого числа без знака. Промежуточная арифметика без знака может быть выполнена (с некоторой заботой) использование 32-разрядных чисел без знака, или это может быть выполнено на 64-разрядных подписанных или числах без знака.

Более точно, работа преобразования знака SignConvert (S; U) определяется как:

  SignConvert(S; U) = Cast32(U)
    if S==0; or
  SignConvert(S; U) = U - Floor(U / 2^S)
    if S>0, (U % 2^S) < 2^S-1, Card(B,H) < 2^32
  SignConvert(S; U) = Cast32(U - Floor(U / 2^S))
    if S>0, (U % 2^S) < 2^S-1, Card(B,H) >= 2^32
  SignConvert(S; U) = -Floor(U / 2^S)-1
    if S>0, (U % 2^S) == 2^S-1
 
Преобразование из большого числа без знака отрицательного 32-разрядного числа через перенос является просто знакомым удрученным к подписанному 32-разрядному интервалу. Это может быть определено математически как:
  Cast32(U) = ((U + 2^31) mod 2^32) - 2^31
 
6.2.1. Дальнейшее Обсуждение Преобразования Знака
Отметьте, что преобразование знака всегда отображает нуль, чтобы обнулить. Читатель может также проверить это, если S> 0, диапазон SignConvert включает [-1.. 1], и что это является плотным и монотонным в любом совершенно положительном или совершенно отрицательном поддиапазоне.

Как следствие определения SignConvert(S;U) биты младшего разряда S U функционируют как знаковый бит. В действительности U делится в поле U0 знака (состоящий из битов младшего разряда S) и мантисса U1 (состоящий из всех других битов U).

В этом альтернативном представлении определения SignConvert, если все биты S U0 устанавливаются, то декодируемое подписанное значение - те дополнение U1. (Так как это включает неопределенное число нулевых битов старшего разряда U, получающееся значение арифметически отрицательно.)

Иначе, если некоторые из битов S U0 являются четкими, то мантисса U1 масштабируется числом возможных значений U0 (то есть, (2^2)-1, если S 2), и U0 включается назад.

Это обеспечивает взаимно-однозначное соответствие между некоторой частью арифметического интервала [0..Card(B,H)-1] и Range(B,H,S).

Целые числа, "одобренные" этим кодированием, являются таковыми из маленькой величины, но у них может быть любой знак. Если S один, у кодирования есть сбалансированное число положительных и отрицательных привилегированных значений. Если S два (или больше), кодирование скашивается к положительным числам, но также и одобряет несколько отрицательных чисел. Мы используем такой codings в другом месте, чтобы закодировать значения, такие как смещения ответвления или дельты сортированных главным образом данных, которые обычно положительны, но иногда отрицательны.

Отметьте это, если S=1, это определение преобразования знака эквивалентно сдвигу вправо без знака, сопровождаемому монопольным - или знакового бита со всеми остающимися битами:

  SignConvert(1; U) = (U >>> 1) ^ -(U & 1)
 

Для S> 0, Диапазон (B, H, S) просто определяется как пересечение 32-разрядного подписанного диапазона [-2^31..2^31-1] с набором SignConvert(S; [0..Card(B,H)-1]), полученный поэлементным приложением преобразования знака в каждое арифметически представимое значение (B, H). Поэтому, мы можем завершить определение Диапазона следующим образом:

  Range(B,H,S) = [-2^31..2^31-1]
    if Card(B,H) >= 2^32, or
  Range(B,H,S) = [0..2^31-1]
    if S=0, 2^31 < Card(B,H) < 2^32, or else
  Range(B,H,S) = [0..Card(B,H)-1]
    if S=0, Card(B,H) <= 2^31

  Range(B,H,S) = [max(  -2^31, min SignConvert(S; Range(B,H,0)) )
               .. min( 2^31-1, max SignConvert(S; Range(B,H,0)) )]
 

(Отметьте: вычисляя границы подписанного кодирования (B, H, S), полезно запустить с самого большого значения без знака М. (B, H, 0) и выполнить преобразование знака на М., M-1, M-2, и т.д., отмечая первое положительное и первую отрицательную величину, с которой встретятся. Они будут содержащими границами диапазона подписанного кодирования.)

6.3. Атрибуты Codings

Количество элементов (B, H) кодирование было определено выше:
  Card(B,H) = (L * (1-H^B)/(1-H)) + H^B
 

Количество элементов (B, H, S) кодирование определяется тем из его диапазона:

  Card(B,H,S) = Card Range(B,H,S) <= Card(B,H)
 

Как определено, диапазон любого кодирования (B, H, S) плотен о нуле и может поэтому быть выражен как закрытый интервал:

  Range(B,H,S) = [Min(B,H,S)..Max(B,H,S)]
  -2^31 <= Min(B,H,S) <= 0
  0     <  Max(B,H,S) <= 2^31-1
 

Определенные дополнительные атрибуты могут быть утверждены codings. Кодирование может или быть подписано или нет, и это может быть полнофункциональное кодирование, или кодирование поддиапазона (или ни один).

(B, H, S) кодирование подписывается, если оно может закодировать по крайней мере одну отрицательную величину. Это - истина, если и только если S является ненулевым, или S является нулем, и Карта (B, H) 2^32 или больше.

(B, H, S) кодирование является полным диапазоном, если Диапазоном (B, H, S) является [-2^31..2^31-1].

Кодирование поддиапазона поставляет меньше чем 2^31 отличные значения. Более точно кодирование (B, H, S) является поддиапазоном если Карта (B, H, S) <= 2^31-1. (Некоторые codings не являются ни полным диапазоном, ни поддиапазоном codings.)

Как следствие этих определений, любой кодирующий, для которого B <=3 является кодированием поддиапазона. Дольше codings может также быть поддиапазонами, если они достаточно "резки". Некоторые примеры (4,192,0), (5,32,0), и (5,32,1).

Кроме того, кодирование без знака (4,256,0) является полным диапазоном, как подписанная версия (4,256,1), но не вдвойне подписанная версия (4,256,2).

Кодирование (4,255,0) не является ни поддиапазоном, ни полнофункциональным кодированием, так как его количество элементов 2^31. Это представляет только неотрицательные 32-разрядные целые числа, но его количество элементов не может быть столь представлено.

6.4. Кодирование Коррелированых Последовательностей

Каждое отдельное целое число в формате архива кодируется согласно некоторому кодированию в схеме (B, H, S) codings. Кроме того, особое внимание обращается на последовательности целых чисел (в "полосах", описанных в другом месте), которые показывают статистическую регулярность. В частности если последовательность целых чисел, как находят, показывает образец небольших, регулярных различий первого порядка, те различия могут быть закодированы вместо значений непосредственно. Это описывается четвертым параметром кодирования, добавленным к (B, H, S) схема.
Имя Диапазон Значение
B [1..5] максимальная длина байта
H [1..256] число высоких значений байта
L [0..255] число значений младшего байта, определенных как (256-ой)
S [0..2] число знаковых битов
D [0..1] порядок кодирования дельты

Если D является нулем, никакой differencing не выполняется, и (B, H, S, 0), кодирование во всех отношениях идентично соответствию (B, H, S) кодирование. Если D один, значения кодируются с точки зрения их последовательных различий.

(Отметьте: Последовательности, которые главным образом монотонно возрастают, будут часто благоприятно кодироваться, используя дельту без знака codings формы (5, H, 0,1).)

Предположите последовательность значений X [мне] дают для некоторого диапазона меня в [0.. N-1]. Эта последовательность будет представимой (B, H, S, 1) кодирование, только если (B, H, S) кодирование является поддиапазоном или полнофункциональным кодированием. (Если это ни один не, там является не законным (B, H, S, 1) кодирование.)

Последовательность X [я] буду представимым, только если есть серия "значений дельты" D [я], частичные суммы которого Sum[j<=i](D[j]) может представить значения X [я].

Каждый (B, H, S, 1) у кодирования есть диапазон, в котором весь X [я] оцениваю, должен лечь. Этот диапазон определяется как Range(B,H,S,1) = Range(B,H,0). Диапазон кодирования дельты (B, H, S, 1) содержит отрицательные числа, только если это основано на полнофункциональном кодировании (B, H, S). Иначе, кодирование дельты может только представить неотрицательные числа. Практически, это не серьезное ограничение, так как практически очень немного элементов полосы отрицательны.

Частичной Сумме сумм [j <=i] (D [j]) позволяют оставить диапазон, но финал X [я] оцениваю, всегда возвращаются в диапазон, добавляя или вычитая кратное число Диапазона Карты (B, H, 0).

Более точно:

  X[i] = Sum[j<=i](D[j]) mod Card(B,H,0)
    if (B,H,S) is sub-range
  X[i] = (int32) Sum[j<=i](D[j])
    if (B,H,S) is full-range
 
(Здесь, бросок к int32 обозначает усечение к 32 битам.)

Отметьте, что реализации могут просто проигнорировать 32-разрядный перенос, вычисляя частичные суммы, если кодирование является полным диапазоном. Иначе, больше заботы должно быть проявлено, чтобы возвратить частичные суммы в диапазон, вычитая или добавляя сеть магазинов количества элементов диапазона. Кроме того, 32-разрядный перенос может быть опасностью для диапазонов размера 2^30 или больше. Возможно реализовать это использование только 32-разрядная подписанная арифметика.

6.5. Кодировки Некоррелированых Значений

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

Компрессор может выбрать использовать основанное на совокупности преобразование кодирования в таких случаях. Это преобразование берет последовательность S арифметики N, оценивает и преобразовывает это в три последовательности значения:

Каждая из этих последовательностей (F, T, и U) поочередно обрабатывается как поддиапазон, и передается с независимым кодированием. Каждое ненулевое значение в T индексирует значение от F, в то время как каждое нулевое значение в T выбирает (чтобы) значение из U:

  S[i] = F[T[i]-1]
    if T[i] != 0
  U = { S[i] such that T[i] == 0 }
 
6.5.1. Таблица Избранного
Таблица F содержит любое число целочисленных значений. Нет никакого ограничения на их число или идентификационные данные, за исключением того, что никакое значение в F не может быть повторено, кроме последнего, и F не должен содержать неиспользованные значения. Последнее значение в F должно быть повторением более раннего возникновения "значения сигнальной метки" F. Эта сигнальная метка отмечает конец таблицы F, позволяя декомпрессор подготовиться читать T и U.

"Центральное значение" X из F определяется как тот элемент F, который является арифметически самым близким к нулю. Если F содержит и положительное X и отрицательный-X минимального абсолютного значения, то-X определяется как центральное значение. (То есть, знак минус является схемой разрешения конфликтов. Центральное значение выбирается, чтобы иметь благоприятное кодирование.)

(Отметьте, что реализации могут сравнить значения для центрированности при использовании 32-разрядного подписанного международного выражения (X>>31)^(X<<1) как ключ сравнения без знака.)

Допустимое значение сигнальной метки является или центральным значением F, или последним значением F. Таким образом, анализируя F, декомпрессор должен искать повторение или центрального значения (до сих пор) или сразу предыдущего значения.

Позвольте K быть числом значений в F, игнорируя повторение значения сигнальной метки. В следующей полосе значения в [1..K] отнесутся (поскольку 1 источник индексирует) к соответствующим элементам F.

6.5.2. Последовательность Маркеров
Последовательность T следует за таблицей F, и кодирует ввод преобразования совокупности в прямом, поэлементно способ.

Каждый элемент T является маркером или для привилегированного или для непривилегированного значения, закодированного в арифметическом диапазоне [0..K]. Каждое ненулевое значение соответствует, чтобы к элементу F, и производит то привилегированное значение. Каждое нулевое значение в T является заполнителем для "непривилегированного" значения, которое все еще неизвестно.

Как упомянуто выше, каждый элемент F должен быть упомянут по крайней мере одним элементом T. Таким образом, следующие два набора должны быть тем же самым:

  { F[T[i]-1] such that T[i] != 0 }
  { F[j] }
 

Статистические данные последовательности T довольно благоприятны для компактного кодирования в подходящем (B, H) схема, предполагая что кодер сделанный хороший выбор для содержания F. Вообще говоря, обычно происходящим входным значениям нужно дать ранние позиции в F.

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

6.5.3. Последовательность Непривилегированных Значений
Третья подпоследовательность состоит из значений, которые не были представимыми, индексирует в таблицу F. Позвольте Z быть числом, обнуляет встреченный в T. Есть упорядоченное, взаимно-однозначное соответствие между Z, обнуляет в T и всех значениях Z U.

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

Декомпрессор может тогда считать F в память, считать T в память, и затем сделать вторую передачу по T, преобразовывая символические стоимости, или обращаясь к F или читая из U по мере необходимости.

6.6. Адаптивные Кодировки

Иногда, в очень длинной последовательности значений, статистика будет медленно изменяться, заставляя первоначально подходящую тактику кодирования стать неподходящей.

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

Адаптивный метод кодирования определяется количеством K, метод A кодирования, который будет использоваться, чтобы закодировать коэффициенты теплопроводности, и другой метод B кодирования, который обработает остальную часть значений.

Так как полосы измеряются контекстом, когда адаптивный метод кодирования будет применен к байтам закодированной полосы, метод будет обеспечен заранее с количеством N значений, чтобы декодировать. Таким образом, после того, как метод A декодировал коэффициенты теплопроводности, метод B будет использоваться, чтобы декодировать остальную часть (N-K) значения в полосе.

6.7. Метакодирование

Каждая полоса в Pack200 архивирует формат, основное кодирование которого не является BYTE1, дополнительно предшествуется серией байтов, названных спецификатором кодирования полосы, которые определяют вторичное кодирование или codings, используемый в той полосе вместо основного кодирования. Декомпрессор должен проанализировать этот спецификатор кодирования и сохранить его далеко прежде, чем он считает любой из элементов полосы. В нескольких дополнительных байтах информации спецификатор кодирования определяет точно, как последующие байты должны декодироваться в значения полосы.

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

6.7.1. Кодирование Структуры Спецификатора
Символьная структура спецификатора кодирования полосы определяется следующей грамматикой. (Эта грамматика независима от грамматики, управляющей структурой полосы, или любой другой грамматикой, появляющейся в других частях этой спецификации.)
  BandCodingSpecifier:
        (Default | BHSDCode | RunCode | PopCode)
  BHSDCode:
        CanonicalBHSDCode | ArbitraryBHSDCode
  CanonicalBHSDCode:
        ( '(1,256,0)' | '(1,256,1)' | ... )
  ArbitraryBHSDCode:
        'arb' ( B H S D )
  B, H, S, D: 
        Integer
  RunCode:
        'run' K ACode BCode
  K:
        Integer
  ACode:
        (Default | BHSDCode | PopCode)
  BCode:
        (Default | BHSDCode | RunCode | PopCode)
  PopCode:
        'pop' ( FCode TCode UCode )
  FCode:
        (Default | BHSDCode | RunCode)
  TCode:
        (Default | BHSDCode | RunCode)
  UCode:
        (Default | BHSDCode | RunCode)
  Integer:
        ( '0' | '1' | ... )
  Default:
        'default'
 
Отметьте, что адаптивные методы кодирования (нетерминалы "RunCode") могут быть объединены в цепочку через нетерминальное "BCode", но не могут быть вложены непосредственно через нетерминальное "ACode". (Поскольку грамматика показывает, они могут быть вложены косвенно через нетерминальное "PopCode".)

Кроме того, методы кодирования совокупности могут содержать адаптивные методы кодирования, и наоборот. Однако, хотя грамматика не показывает этот факт, методы кодирования совокупности не должны быть вложены, даже косвенно.

Не все возможные целочисленные значения K и L являются одинаково хорошо выразимыми. Намеченные значения K соразмерны с окнами компрессора, и намеченные значения L являются параметрами резкости для кодировок BHS.

6.7.2. Кодирование Семантики Спецификатора
В любой точке содержание полосы декодируется под управлением трех сведений:

Мы обозначаем приложение S в контексте N и D как "S (N, D)". Это приложение декодирует до элементов N переданных данных полосы.

Непосредственно перед тем, как полоса получается, декомпрессор знает ожидаемую длину полосы N и метод D кодирования значения по умолчанию, определенный статически как основное кодирование полосы. Декомпрессор тогда читает нуль или больше байтов, которые составляют спецификатор кодирования полосы, и декодирует элементы N данных полосы, основанных на спецификаторе кодирования полосы.

Когда спецификатор кодирования является 'значением по умолчанию', N значения декодируются, используя значение по умолчанию, кодирующее D, который является основным кодированием полосы. (Это правило необходимо, если первый элемент полосы, кажется, представляет непустой спецификатор кодирования. Такой спецификатор кодирования значения по умолчанию является единственным видом, который компрессор обязывается испустить; остальные являются все дополнительными.)

Когда спецификатор кодирования является другим BHSDCode, N значения декодируются, используя то кодирование. Окружающее значение по умолчанию D игнорируется.

Когда спецификатор кодирования является 'выполнением' K, ACode, BCode, два шага делаются. Во-первых, спецификатор ACode является данным контролем, как ACode (K, D). Таким образом, N временно устанавливается в K. Во-вторых, спецификатор BCode является данным контролем как BCode (N-K, D). (Отметьте: Если N будет бесконечностью, то N-K также будет бесконечностью.) В обоих шагах D остается неизменным, так, чтобы возникновения 'значения по умолчанию' для ACode или BCode заставили D использоваться.

Это недопустимо для спецификатора кодирования 'выполнения', чтобы определить K нуля, или для этого, чтобы использоваться, чтобы декодировать выполнение K или меньшего количества значений.

Когда спецификатор кодирования является 'выталкиванием' FCode, TCode, UCode, три шага делаются. Во-первых, FCode применяется как FCode (бесконечность, D). Декодирование F оценивает остановки, когда с первым двойным значением встречаются. (Как определено в разделе выше по кодированию совокупности, то двойное значение действия как сигнальная метка, и должно сразу быть или самое "центральное" чтение значения, или иначе значение до значения сигнальной метки.) Позволяют K быть числом уникальных декодируемых значений.

Во время декодирования значений F FCode каждый спецификатор 'выполнения' в FCode должен исчерпать свое количество 'K', не декодируя значение сигнальной метки. Таким образом, сигнальная метка должна декодироваться последним простым BHSD, кодирующим в FCode.

Во втором шаге различное кодирование используется TCode, так как значения T, как ожидают, будут плотным кодированием. TCode применяется как TCode (N, D), и маркеры читаются, которые определяют значения полосы, которые будут поставлены. (Отметьте, что 'выталкивать' метод кодирования может только быть применен, если предоставленное значение N конечно. Это будет истиной, так как единственные полосы, которые читаются с бесконечным N, являются полосами байта, такими как bc_codes.) Позволяют Z быть числом, обнуляет декодируемое использование TCode.

Третий шаг должен использовать UCode, чтобы декодировать значения Z, используя исходную кодировку по умолчанию D. UCode применяется как U (Z, D). Получающаяся полоса производится из последовательности T, как задокументировано выше, заменой обнуляет в последовательности T последовательными значениями U, и замене других элементов последовательности T индексированными в последовательности F.

Это недопустимо для 'выталкивать' спецификатора кодирования, который будет использоваться, чтобы декодировать выполнение никаких значений, или бесконечного числа значений. Если Z (число непривилегированных значений) является нулем, это недопустимо для UCode, чтобы быть чем-либо кроме 'значения по умолчанию'.

6.7.3. Кодирование Метакодирования Спецификатора
Компрессор использует время, байтовое кодирование, чтобы передать спецификатор кодирования полосы. Хотя "небольшой язык" выше позволяет широкий диапазон кодировок, практически многие из них подобны в производительности и применимости. Это не является необходимым или требуемым, чтобы позволить компрессору полную свободу определить любой мыслимый спецификатор кодирования полосы. Вместо этого метакодирование, описанное в этом разделе, позволяет компрессору выбирать из ограниченного, но полезного набора вторичных кодировок. Именно до компрессора, чтобы сделать выбор улучшает сжатие; эвристика или алгоритм, который управляет таким выбором, выходят за рамки этой спецификации.

Общий спецификатор кодирования полосы 'значения по умолчанию' кодируется в пути, который часто не требует никаких дополнительных байтов. Если у полосы нет никаких элементов, никакой парсинг вообще не делается. Иначе, если кодировка по умолчанию полосы имеет переменную длину, декомпрессор обязывается декодировать одно значение X от начальных байтов полосы, используя значение по умолчанию полосы, кодирующее D. Если возможный, значение X преобразовывается в XB значения байта без знака, который берется, чтобы быть первым байтом спецификатора кодирования полосы, и X будет отброшен. Иначе, спецификатор кодирования полосы берется, чтобы быть 'значением по умолчанию', и таким образом, D применяется ко всей полосе, включая байты, которые произвели начальное значение X.

D должен иметь форму (B, H, S) или (B, H, S, D), где B> 1 и H <256. Значение является D, не важно декодированию первого значения, и декодирование X делается, используя (B, H, S, 0). Если S не является нулем, и если значение X находится в диапазоне [-256..-1], байт спецификатора кодирования, XB определяется, поскольку XB = (-1-X), и X отбрасывается. Иначе, если S является нулем, и если значение X находится в диапазоне [(256-ое).. (511-ый)], байт спецификатора кодирования XB определяется, поскольку XB = (X-(256-H)), и X отбрасывается. Иначе, нет байта спецификатора кодирования, XB, и X является первым значением полосы, как описано выше.

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

Если полоса действительно запускает с элемента X1 в диапазоне ([-256..-1] или [L,L+255]), который требует производства полосы specififer байт, XB, но компрессор хочет использовать кодировку по умолчанию, компрессор обязан определять заголовок полосы, чтобы X1 не вводят в заблуждение декомпрессор. Если компрессор хочет сохранить кодирование значения по умолчанию, он должен в таких случаях определять явный спецификатор кодирования 'значения по умолчанию', используя значение XB нуля (как определено ниже). Этот нулевой XB передается, в зависимости от кодировки по умолчанию как X значений-1 (обычно байт 1) или L (обычно байты 192,0).

(Непосредственное следствие этого проекта - то, что у полос байта никогда не может быть кодировок не по умолчанию, но все другие полосы могут, так как у всех других полос есть значение по умолчанию encodigns, которые являются переменной длиной и имеют большой динамический диапазон. Значения "escape", выбранные для X, редки практически, таким образом, они обычно не путаются с реальными данными полосы. Добавление дополнительного нулевого значения, чтобы вновь подтвердить значение по умолчанию будет всегда стоить одного дополнительного байта перед фактическими данными полосы, и никакими дополнительными байтами в полосе band_headers. Вообще, кодирование явных, X значений будут всегда требовать двух байтов, если S будет нулем, и самое большее два байта, если S не является нулем.)

band_headers полосы передает неначальные байты заголовка полосы (если любой) каждой полосы, у которой есть заголовок полосы. Порядок передачи является непротиворечивым с полным порядком всех полос в архиве, как дано в грамматике полосы существующей спецификации. Длина band_headers независимо определяется (как #band_headers_size) в заголовке архива. (Это должно быть четким, что декомпрессор должен найти конец band_headers прежде, чем это сможет считать дальнейшие полосы.)

Таким образом кодирование спецификатора кодирования состоит из последовательности байтов: начальный байт XB, и нуль или больше неначальных байтов, взятых от band_headers. Кодировки небольшого языка, определенного в предыдущем разделе, следующие. Кодирование 'значение по умолчанию' является нулевым байтом. Из всех возможных кодировок BHSDCode последовательность 115 канонических кодировок (определенный ниже) выбирается, чтобы покрыть ожидаемый диапазон использования. BHSDCode представляется как единственный байт, значение которого является индексированием (на основе 1) из выбранного канонического кодирования.

  Enc{default}  = (0)
  Enc{CanonicalBHSDCode} = value in [1..115]
 

Специальное значение 116 представляет произвольное, возможно неканонический код BHSD, описанный в следующем байте.

  Enc{ arb ( B H S D ) } =
      116
    & (D:[0..1] + 2*S[0..2] + 8*(B:[1..5]-1))
    & (H[1..256]-1):
 
Значение B должно быть в диапазоне [1.. 5]. Значение S должно быть в диапазоне [0.. 2]. Значение H должно быть в диапазоне [1.. 256]. Значение D должно быть в диапазоне [0.. 1]. (Эти диапазоны являются содержащими.), Кроме того, если B 1, H должен быть 256, и если H 256, B не должен быть 5.

Кодировки конструкции 'выполнения' начинаются с байта в [117.. 140], и может сопровождаться дополнительным Кбайтом байта и затем одним или двумя спецификаторами кодирования ACode и BCode. Смещение от 117 представляет поразрядный следующие данные:

Последние два бита совместно кодируются в значении ABDef. Они никогда не оба истина.
  Enc{ run ( K ACode BCode ) } =
      (117 + (KX:[0..3]) + 4*(KBFlag:[0..1]) + 8*(ABDef:[0..2]))
    & KB: one of [0..255] if KBFlag=1
    & Enc{ ACode } if ADef=0  (ABDef != 1)
    & Enc{ BCode } if BDef=0  (ABDef != 2)
 

После того, как ведущий байт анализируется, Кбайт байта ожидается, если KBFlag будет установлен, иначе Кбайту неявно дают значение 3.

Коэффициент теплопроводности для конструкции 'выполнения' может взять диапазон значений, и определяется следующим образом:

  K = (KB+1) * 16^KX
 

Кодирование ACode, как понимают, является 'значением по умолчанию', если бит ADef устанавливается. Иначе, представление ACode анализируется затем. Наконец, кодирование BCode, как понимают, является 'значением по умолчанию', если бит BDef устанавливается. Иначе, представление BCode анализируется последнее. И ADef и BDef могут быть четкими, но оба не могут быть установлены.

'Выталкивать' кодировки конструкции начинаются с байта в [141.. 188], и может сопровождаться один, два, или три спецификатора кодирования, FCode, UCode, и TCode. Смещение от 141 поразрядный кодирует следующие данные:

Последние два значения совместно кодируются в значении TDefL.
  Enc{ pop ( FCode TCode UCode ) }
    = (141 + (FDef:[0..1]) + 2*UDef:[0..1] + 4*(TDefL:[0..11]))
    & Enc{ FCode } if FDef=0
    & Enc{ TCode } if TDef=0  (TDefL==0)
    & Enc{ UCode } if UDef=0
 

Если TDef является нулем, явный спецификатор кодирования определяет TCode, и параметр L не присутствует. Если TDef один, параметр L присутствует и получается из TDefL согласно следующей таблице:

TDefL L
1 4
2 8
3 16
4 32
5 64
6 128
7 192
8 224
9 240
10 248
11 252

Если параметр L присутствует, TCode получается из значений K и L. Если K <256, то TCode является BYTE1 (1,255,0), и L, игнорируется. Иначе, TCode (B, H, S) кодирование, где S=0, H = (256-L), и B является самым маленьким значением так, что [0.. K] содержится в Диапазоне (B, H, S). (Это недопустимо, чтобы определить L, настолько большой, что Диапазон (5,256-L, 0) не содержит K.),

Кодирование FCode, как понимают, является 'значением по умолчанию', если бит FDef устанавливается. Иначе, представление FCode сразу анализируется после начального байта. Кодирование TCode, как понимают, получается из K и L, если бит TDef устанавливается. Иначе, представление TCode анализируется затем. Наконец, кодирование UCode, как понимают, является 'значением по умолчанию', если бит UDef устанавливается. Иначе, представление UCode анализируется последнее.

6.7.4. Канонический BHSD Codings
Вот список всего канонического BHSD codings. Эти codings разрабатываются, чтобы соответствовать разнообразное разнообразие диапазонов значений полосы и статистики.
индексировать Кодирование BHSD
1 (1,256,0)
2 (1,256,1)
3 (1,256,0,1)
4 (1,256,1,1)
5 (2,256,0)
6 (2,256,1)
7 (2,256,0,1)
8 (2,256,1,1)
9 (3,256,0)
10 (3,256,1)
11 (3,256,0,1)
12 (3,256,1,1)
13 (4,256,0)
14 (4,256,1)
15 (4,256,0,1)
16 (4,256,1,1)
17 (5, 4,0)
18 (5, 4,1)
19 (5, 4,2)
20 (5, 16,0)
21 (5, 16,1)
22 (5, 16,2)
23 (5, 32,0)
24 (5, 32,1)
25 (5, 32,2)
26 (5, 64,0)
27 (5, 64,1)
28 (5, 64,2)
29 (5,128,0)
30 (5,128,1)
31 (5,128,2)
32 (5, 4,0,1)
33 (5, 4,1,1)
34 (5, 4,2,1)
35 (5, 16,0,1)
36 (5, 16,1,1)
37 (5, 16,2,1)
38 (5, 32,0,1)
39 (5, 32,1,1)
40 (5, 32,2,1)
41 (5, 64,0,1)
42 (5, 64,1,1)
43 (5, 64,2,1)
44 (5,128,0,1)
45 (5,128,1,1)
46 (5,128,2,1)
47 (2,192,0)
48 (2,224,0)
49 (2,240,0)
50 (2,248,0)
51 (2,252,0)
52 (2, 8,0,1)
53 (2, 8,1,1)
54 (2, 16,0,1)
55 (2, 16,1,1)
56 (2, 32,0,1)
57 (2, 32,1,1)
58 (2, 64,0,1)
59 (2, 64,1,1)
60 (2,128,0,1)
61 (2,128,1,1)
62 (2,192,0,1)
63 (2,192,1,1)
64 (2,224,0,1)
65 (2,224,1,1)
66 (2,240,0,1)
67 (2,240,1,1)
68 (2,248,0,1)
69 (2,248,1,1)
70 (3,192,0)
71 (3,224,0)
72 (3,240,0)
73 (3,248,0)
74 (3,252,0)
75 (3, 8,0,1)
76 (3, 8,1,1)
77 (3, 16,0,1)
78 (3, 16,1,1)
79 (3, 32,0,1)
80 (3, 32,1,1)
81 (3, 64,0,1)
82 (3, 64,1,1)
83 (3,128,0,1)
84 (3,128,1,1)
85 (3,192,0,1)
86 (3,192,1,1)
87 (3,224,0,1)
88 (3,224,1,1)
89 (3,240,0,1)
90 (3,240,1,1)
91 (3,248,0,1)
92 (3,248,1,1)
93 (4,192,0)
94 (4,224,0)
95 (4,240,0)
96 (4,248,0)
97 (4,252,0)
98 (4, 8,0,1)
99 (4, 8,1,1)
100 (4, 16,0,1)
101 (4, 16,1,1)
102 (4, 32,0,1)
103 (4, 32,1,1)
104 (4, 64,0,1)
105 (4, 64,1,1)
106 (4,128,0,1)
107 (4,128,1,1)
108 (4,192,0,1)
109 (4,192,1,1)
110 (4,224,0,1)
111 (4,224,1,1)
112 (4,240,0,1)
113 (4,240,1,1)
114 (4,248,0,1)
115 (4,248,1,1)

7. Устойчивость Вывода Декомпрессора

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

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

Вообще, порядок элементов в распакованном файле class должен быть непротиворечивым с порядком передачи в архиве Pack200. Например, порядок полей class, объявленных в файле class, должен соответствовать порядку, в, котором что полевые дескрипторы class были переданы в полосе field_descr. (Это также, оказывается, соответствует порядку в полосах field_flags.) Эта таблица дает все необходимые корреспонденции порядка файла class с порядком передачи архива:

элемент в
Файл class
полоса, который
определяет порядок
реализованные интерфейсы class _interface
объявленные поля field_descr
объявленные методы method_descr
список обработчика кода code_handler_start_P
Список атрибутов class class _flags, class _attr_indexes
полевой список атрибутов field_flags, field_attr_indexes
список атрибутов метода method_flags, method_attr_indexes
кодируйте список атрибутов code_attr_indexes
постоянные записи пула cp_Utf8, и т.д. (см. ниже),

Вместе, эти необходимые корреспонденции порядка определяют точное содержание распакованного файла class. Упорядочивание интерфейсов, полей, методов, и обработчиков исключений непосредственно определяется упорядочиванием полос, которые передают их.

7.1. Упорядочивание Списков атрибутов

Списки атрибутов для классов, полей, и методов должны начаться со всех атрибутов, переданных из-за флаговых битов набора. Порядок должен быть, индексируют порядок (от LSB до MSB в слове флага). После любых возможных вызванных флагом атрибутов список должен тогда содержать любые атрибуты переполнения. Любой список атрибутов с атрибутами переполнения представит их в том же самом порядке, как их разметки были переданы в соответствующей серии значений от class_attr_indexes, field_attr_indexes, method_attr_indexes, или code_attr_indexes. Отметьте, что расположение атрибута, чье индексируют, меньше чем 32 могут быть определены нуль или времена через флаговый бит. Независимо, это может также быть определено нуль или больше раз через возникновения в полосе, передающей разметки атрибута переполнения.

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

7.2. Упорядочивание Постоянных Пулов

Постоянный cp(X) пула распакованного файла X class определяется, как будто последующей обработкой X и cp_All после того, как декомпрессор уже произвел большинство из X. Определенно, предположите, что содержание X определяется, за исключением того, что:

Затем cp(X) определяется, как будто следующими шагами, которые заполняют его от глобального постоянного пула cp_All, и также потенциально производят атрибут InnerClasses для X.

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

С ic_Relevant(X) и дополнительно переданным ic_Local(X) в руке, должен затем решить декомпрессор, сохранить ли атрибут InnerClasses ic_Stored(X) для X, используя эти шаги.

С последними вкладами от вложенных записей class декомпрессор заканчивает постоянный пул, используя эти шаги:

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

Отметьте, что упорядочивание cp(X) является непротиворечивым с тем из cp_All, за исключением того, что некоторые ссылки подписи перенаправляются к эквивалентным существующим ранее элементам cp_Utf8, и все операнды ldc байт-кодов вызываются к передней стороне постоянного пула.

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

8. Приложения

8.1. Приложение: Список Полос

Вот список всех полос в порядке, они должны произойти в архиве. Этот список не является частью спецификации Pack200, но это представляется, чтобы помочь разъяснить значение грамматики в спецификации, надлежащей, который определяет имена и упорядочивание полос. Четыре возникновения замещающего знака... обращаются к точкам вставки, где компрессор может вставить переменные числа дополнительных полос, чтобы помочь передать необычные строки или нестандартные атрибуты. Другие эллипсы обращаются к повторениям полос метаданных, которые это было бы слишком утомительно, чтобы включать.
Полоса Значение по умолчанию
кодирование
Длина Постоянный пул
упомянутый
archive_magic BYTE1 [4]  
archive_header UNSIGNED5 [26]  
band_headers BYTE1 [...]  
cp_Utf8_prefix DELTA5 [MAX(0,#cp_Utf8_count-2)]  
cp_Utf8_suffix UNSIGNED5 [MAX(0,#cp_Utf8_count-1)]  
cp_Utf8_chars CHAR3 [SUM(*cp_Utf8_suffix)]  
cp_Utf8_big_suffix DELTA5 [COUNT(0,*cp_Utf8_suffix)]  
{cp_Utf8_big_chars...} DELTA5 [*cp_Utf8_big_suffix[i]]  
cp_Int UDELTA5 [#cp_Int_count]  
cp_Float UDELTA5 [#cp_Float_count]  
cp_Long_hi UDELTA5 [#cp_Long_count]  
cp_Long_lo DELTA5 [#cp_Long_count]  
cp_Double_hi UDELTA5 [#cp_Double_count]  
cp_Double_lo DELTA5 [#cp_Double_count]  
cp_String UDELTA5 [#cp_String_count] cp_Utf8
cp_Class UDELTA5 [#cp_Class_count] cp_Utf8
cp_Signature_form DELTA5 [#cp_Signature_count] cp_Utf8
cp_Signature_classes UDELTA5 [COUNT('L',...)] cp_Class
cp_Descr_name DELTA5 [#cp_Descr_count] cp_Utf8
cp_Descr_type UDELTA5 [#cp_Descr_count] cp_Signature
cp_Field_class DELTA5 [#cp_Field_count] cp_Class
cp_Field_desc UDELTA5 [#cp_Field_count] cp_Descr
cp_Method_class DELTA5 [#cp_Method_count] cp_Class
cp_Method_desc UDELTA5 [#cp_Method_count] cp_Descr
cp_Imethod_class DELTA5 [#cp_Imethod_count] cp_Class
cp_Imethod_desc UDELTA5 [#cp_Imethod_count] cp_Descr
cp_MethodHandle_refkind DELTA5 [#cp_MethodHandle_count]  
cp_MethodHandle_member UDELTA5 [#cp_MethodHandle_count] cp_All
cp_MethodType UDELTA5 [#cp_MethodType_count] cp_Signature  
cp_BootstrapMethod_ref DELTA5 [#cp_BootstrapMethod_count] cp_MethodHandle
cp_BootstrapMethod_arg_count UDELTA5 [#cp_BootstrapMethod_count]arg_tt>  
cp_BootstrapMethod_arg DELTA5 [SUM(*class_interface_count)] cp_All
cp_InvokeDynamic_spec DELTA5 [#cp_InvokeDynamic_count] cp_BootstrapMethod
cp_InvokeDynamic_descr UDELTA5 [#cp_InvokeDynamic_count] cp_Descr
attr_definition_headers BYTE1 [#attr_definition_count]  
attr_definition_name UNSIGNED5 [#attr_definition_count] cp_Utf8
attr_definition_layout UNSIGNED5 [#attr_definition_count] cp_Utf8
ic_this_class UDELTA5 [#ic_count] cp_Class
ic_flags UNSIGNED5 [#ic_count]  
ic_outer_class DELTA5 [COUNT(1<<16,...)] cp_Class
ic_name DELTA5 [COUNT(1<<16,...)] cp_Utf8
class_this DELTA5 [#class_count] cp_Class
class_super DELTA5 [#class_count] cp_Class
class_interface_count DELTA5 [#class_count]  
class_interface DELTA5 [SUM(*class_interface_count)] cp_Class
class_field_count DELTA5 [#class_count]  
class_method_count DELTA5 [#class_count]  
field_descr DELTA5 [SUM(*class_field_count)] cp_Descr
field_flags_hi UNSIGNED5 [SUM(*class_field_count)*#have_field_flags_hi]  
field_flags_lo UNSIGNED5 [SUM(*class_field_count)]  
field_attr_count UNSIGNED5 [COUNT(1<<16,...)]  
field_attr_indexes UNSIGNED5 [SUM(*field_attr_count)]  
field_attr_calls UNSIGNED5 [...]  
field_ConstantValue_KQ UNSIGNED5 [COUNT(ConstantValue,...)] cp_Int, cp_Float, etc.
field_Signature_RS UNSIGNED5 [COUNT(Signature,...)] cp_Signature
field_RVA_anno_N UNSIGNED5 [...]  
field_RVA_type_RS UNSIGNED5 [...] cp_Signature
field_RVA_pair_N UNSIGNED5 [...]  
field_RVA_name_RU UNSIGNED5 [...] cp_Utf8
field_RVA_T BYTE1 [...]  
field_RVA_caseI_KI UNSIGNED5 [...] cp_Int
field_RVA_caseD_KD UNSIGNED5 [...] cp_Double
field_RVA_caseF_KF UNSIGNED5 [...] cp_Float
field_RVA_caseJ_KJ UNSIGNED5 [...] cp_Long
field_RVA_casec_RS UNSIGNED5 [...] cp_Signature
field_RVA_caseet_RS UNSIGNED5 [...] cp_Signature
field_RVA_caseec_RU UNSIGNED5 [...] cp_Utf8
field_RVA_cases_RU UNSIGNED5 [...] cp_Utf8
field_RVA_casearray_N UNSIGNED5 [...]  
field_RVA_nesttype_RS UNSIGNED5 [...] cp_Signature
field_RVA_nestpair_N UNSIGNED5 [...]  
field_RVA_nestname_RU UNSIGNED5 [...] cp_Utf8
field_RIA_anno_N UNSIGNED5 [...]  
{field_RIA_...}  
field_RIA_nestname_RU UNSIGNED5 [...] cp_Utf8
{field_attr_element_bands...} (различный) [...] (various)
method_descr MDELTA5 [SUM(*class_method_count)] cp_Descr
method_flags_hi UNSIGNED5 [SUM(*class_method_count)*#have_method_flags_hi]  
method_flags_lo UNSIGNED5 [SUM(*class_method_count)]  
method_attr_count UNSIGNED5 [COUNT(1<<16,...)]  
method_attr_indexes UNSIGNED5 [SUM(*method_attr_count)]  
method_attr_calls UNSIGNED5 [...]  
method_Exceptions_N UNSIGNED5 [COUNT(Exceptions,...)]  
method_Exceptions_RC UNSIGNED5 [SUM(*method_Exceptions_N)] cp_Class
method_Signature_RS UNSIGNED5 [COUNT(Signature,...)] cp_Signature
method_RVA_anno_N UNSIGNED5 [...]  
method_RVA_type_RS UNSIGNED5 [...] cp_Signature
method_RVA_pair_N UNSIGNED5 [...]  
method_RVA_name_RU UNSIGNED5 [...] cp_Utf8
method_RVA_T BYTE1 [...]  
method_RVA_caseI_KI UNSIGNED5 [...] cp_Int
method_RVA_caseD_KD UNSIGNED5 [...] cp_Double
method_RVA_caseF_KF UNSIGNED5 [...] cp_Float
method_RVA_caseJ_KJ UNSIGNED5 [...] cp_Long
method_RVA_casec_RS UNSIGNED5 [...] cp_Signature
method_RVA_caseet_RS UNSIGNED5 [...] cp_Signature
method_RVA_caseec_RU UNSIGNED5 [...] cp_Utf8
method_RVA_cases_RU UNSIGNED5 [...] cp_Utf8
method_RVA_casearray_N UNSIGNED5 [...]  
method_RVA_nesttype_RS UNSIGNED5 [...] cp_Signature
method_RVA_nestpair_N UNSIGNED5 [...]  
method_RVA_nestname_RU UNSIGNED5 [...] cp_Utf8
method_RIA_anno_N UNSIGNED5 [...]  
{method_RIA_...}  
method_RIA_nestname_RU UNSIGNED5 [...] cp_Utf8
method_RVPA_param_NB BYTE1 [...]  
method_RVPA_anno_N UNSIGNED5 [...]  
{method_RVPA_...}  
method_RVPA_nestname_RU UNSIGNED5 [...] cp_Utf8
method_RIPA_param_NB BYTE1 [...]  
method_RIPA_anno_N UNSIGNED5 [...]  
{method_RIPA_...}  
method_RIPA_nestname_RU UNSIGNED5 [...] cp_Utf8
method_AD_T BYTE1 [...]  
method_AD_caseI_KI UNSIGNED5 [...] cp_Int
method_AD_caseD_KD UNSIGNED5 [...] cp_Double
method_AD_caseF_KF UNSIGNED5 [...] cp_Float
method_AD_caseJ_KJ UNSIGNED5 [...] cp_Long
method_AD_casec_RS UNSIGNED5 [...] cp_Signature
method_AD_caseet_RS UNSIGNED5 [...] cp_Signature
method_AD_caseec_RU UNSIGNED5 [...] cp_Utf8
method_AD_cases_RU UNSIGNED5 [...] cp_Utf8
method_AD_casearray_N UNSIGNED5 [...]  
method_AD_nesttype_RS UNSIGNED5 [...] cp_Signature
method_AD_nestpair_N UNSIGNED5 [...]  
method_AD_nestname_RU UNSIGNED5 [...] cp_Utf8
{method_attr_element_bands...} (различный) [...] (various)
class_flags_hi UNSIGNED5 [#class_count*#have_class_flags_hi]  
class_flags_lo UNSIGNED5 [#class_count]  
class_attr_count UNSIGNED5 [COUNT(1<<16,...)]  
class_attr_indexes UNSIGNED5 [SUM(*class_attr_count)]  
class_attr_calls UNSIGNED5 [...]  
class_SourceFile_RUN UNSIGNED5 [COUNT(SourceFile,...)] null|cp_Utf8
class_EnclosingMethod_RC UNSIGNED5 [COUNT(EnclosingMethod,...)] cp_Class
class_EnclosingMethod_RDN UNSIGNED5 [COUNT(EnclosingMethod,...)] null|cp_Descr
class_Signature_RS UNSIGNED5 [COUNT(Signature,...)] cp_Signature
class_RVA_anno_N UNSIGNED5 [...]  
class_RVA_type_RS UNSIGNED5 [...] cp_Signature
class_RVA_pair_N UNSIGNED5 [...]  
class_RVA_name_RU UNSIGNED5 [...] cp_Utf8
class_RVA_T BYTE1 [...]  
class_RVA_caseI_KI UNSIGNED5 [...] cp_Int
class_RVA_caseD_KD UNSIGNED5 [...] cp_Double
class_RVA_caseF_KF UNSIGNED5 [...] cp_Float
class_RVA_caseJ_KJ UNSIGNED5 [...] cp_Long
class_RVA_casec_RS UNSIGNED5 [...] cp_Signature
class_RVA_caseet_RS UNSIGNED5 [...] cp_Signature
class_RVA_caseec_RU UNSIGNED5 [...] cp_Utf8
class_RVA_cases_RU UNSIGNED5 [...] cp_Utf8
class_RVA_casearray_N UNSIGNED5 [...]  
class_RVA_nesttype_RS UNSIGNED5 [...] cp_Signature
class_RVA_nestpair_N UNSIGNED5 [...]  
class_RVA_nestname_RU UNSIGNED5 [...] cp_Utf8
class_RIA_anno_N UNSIGNED5 [...]  
{class_RIA_...}  
class_RIA_nestname_RU UNSIGNED5 [...] cp_Utf8
class_InnerClasses_N UNSIGNED5 [COUNT(InnerClasses,...)]  
class_InnerClasses_RC UNSIGNED5 [SUM(*class_InnerClasses_N)] cp_Class
class_InnerClasses_F UNSIGNED5 [SUM(*class_InnerClasses_N)]  
class_InnerClasses_outer_RCN UNSIGNED5 [COUNT(!=0,*class_InnerClasses_F)] null|cp_Class
class_InnerClasses_name_RUN UNSIGNED5 [COUNT(!=0,*class_InnerClasses_F)] null|cp_Utf8
class_file_version_minor_H UNSIGNED5 [COUNT(version,...)]  
class_file_version_major_H UNSIGNED5 [COUNT(version,...)]  
{class_attr_element_bands...} (различный) [...] (various)
code_headers BYTE1 [COUNT(Code,...)]  
code_max_stack UNSIGNED5 [COUNT(0,*code_headers)]  
code_max_na_locals UNSIGNED5 [COUNT(0,*code_headers)]  
code_handler_count UNSIGNED5 [COUNT(0,*code_headers)]  
code_handler_start_P BCI5 [SUM(*code_header_count)]  
code_handler_end_PO BRANCH5 [SUM(*code_header_count)]  
code_handler_catch_PO BRANCH5 [SUM(*code_header_count)]  
code_handler_class_RCN UNSIGNED5 [SUM(*code_header_count)] null|cp_Class
code_flags_hi UNSIGNED5 [...*#have_code_flags_hi]  
code_flags_lo UNSIGNED5 [...]  
code_attr_count UNSIGNED5 [COUNT(1<<16,...)]  
code_attr_indexes UNSIGNED5 [SUM(*code_attr_count)]  
code_attr_calls UNSIGNED5 [...]  
code_StackMapTable_N UNSIGNED5 [COUNT(StackMapTable,...)]  
code_StackMapTable_frame_T BYTE1 [SUM(*code_StackMapTable_N)]  
code_StackMapTable_local_N UNSIGNED5 [COUNT(255,*code_StackMapTable_frame_T)]  
code_StackMapTable_stack_N UNSIGNED5 [COUNT(255,*code_StackMapTable_frame_T)]  
code_StackMapTable_offset UNSIGNED5 [...]  
code_StackMapTable_T BYTE1 [...]  
code_StackMapTable_RC UNSIGNED5 [COUNT(7,*code_StackMapTable_T)]  
code_StackMapTable_P BCI5 [COUNT(8,*code_StackMapTable_T)]  
code_LineNumberTable_N UNSIGNED5 [...]  
code_LineNumberTable_bci_P BCI5 [...]  
code_LineNumberTable_line UNSIGNED5 [...]  
code_LocalVariableTable_N UNSIGNED5 [...]  
code_LocalVariableTable_bci_P BCI5 [...]  
code_LocalVariableTable_span_O BRANCH5 [...]  
code_LocalVariableTable_name_RU UNSIGNED5 [...] cp_Utf8
code_LocalVariableTable_type_RS UNSIGNED5 [...] cp_Signature
code_LocalVariableTable_slot UNSIGNED5 [...]  
code_LocalVariableTypeTable_N UNSIGNED5 [...]  
code_LocalVariableTypeTable_bci_P BCI5 [...]  
code_LocalVariableTypeTable_span_O BRANCH5 [...]  
code_LocalVariableTypeTable_name_RU UNSIGNED5 [...] cp_Utf8
code_LocalVariableTypeTable_type_RS UNSIGNED5 [...] cp_Signature
code_LocalVariableTypeTable_slot UNSIGNED5 [...]  
{code_attr_element_bands...} (различный) [...] (various)
bc_codes BYTE1 [...]  
bc_case_count UNSIGNED5 [COUNT(switch,*bc_codes)]  
bc_case_value DELTA5 [...]  
bc_byte BYTE1 [...]  
bc_short DELTA5 [...]  
bc_local UNSIGNED5 [...]  
bc_label BRANCH5 [...]  
bc_intref DELTA5 [...] cp_Int
bc_floatref DELTA5 [...] cp_Float
bc_longref DELTA5 [...] cp_Long
bc_doubleref DELTA5 [...] cp_Double
bc_stringref DELTA5 [...] cp_String
bc_loadablevalueref DELTA5 [COUNT({qldc,qldc_w},*bc_codes)] cp_All
bc_classref UNSIGNED5 [...] cp_Class
bc_fieldref DELTA5 [...] cp_Field
bc_methodref UNSIGNED5 [...] cp_Method
bc_imethodref DELTA5 [...] cp_Imethod
bc_thisfield UNSIGNED5 [...] cp_Field subsequence
bc_superfield UNSIGNED5 [...] cp_Field subsequence
bc_thismethod UNSIGNED5 [...] cp_Method subsequence
bc_supermethod UNSIGNED5 [...] cp_Method subsequence
bc_initref UNSIGNED5 [...] cp_Method subsequence
bc_escref UNSIGNED5 [COUNT(ref_escape,*bc_codes)] cp_All
bc_escrefsize UNSIGNED5 [...]  
bc_escsize UNSIGNED5 [...]  
bc_escbyte BYTE1 [...]  
file_name UNSIGNED5 [#file_count] cp_Utf8
file_size_hi UNSIGNED5 [#file_count*(#have_file_size_hi)]  
file_size_lo UNSIGNED5 [#file_count]  
file_modtime DELTA5 [#file_count*(#have_file_modtime)]  
file_options UNSIGNED5 [#file_count*(#have_file_options)]  
file_bits BYTE1 [SUM(*file_size)]  

8.2. Приложение: Иллюстрации псевдокода

8.2.1. Представление cp_Utf8 Постоянный Пул

Следующий псевдокод утверждает отношения, как описано выше, между длинами полосы и содержанием, и cp_Utf8 постоянные элементы пула. (Этот код просто комментирует спецификацию, данную выше; это самостоятельно не добавляет новую информацию к спецификации.)
  assert(cp_Utf8[0].equals(""));
  int cursor = 0;
  int big_cursor = 0;
  for (int i = 1; i < cp_Utf8_count; i++) {
    String thisString = cp_Utf8[i];

    int prefix = (i == 1)? 0: cp_Utf8_prefix[i-2];
    int suffix = thisString.length() - prefix;
    String prevString = cp_Utf8[i-1];
    String prevPrefix = prevString.substring(0, prefix);
    String thisPrefix = thisString.substring(0, prefix);
    assert(prevPrefix.equals(thisPrefix));

    int small_suffix = cp_Utf8_suffix[i-1];
    char[] suffix_chars;
    int offset;
    if (small_suffix != 0) {
      assert(suffix == small_suffix);
      suffix_chars = cp_Utf8_chars;
      offset = cursor;
      cursor += suffix;
    } else {
      assert(suffix == cp_Utf8_big_suffix[big_cursor]);
      suffix_chars = cp_Utf8_big_chars[big_cursor];
      offset = 0;
      assert(suffix == suffix_chars.length);
      big_cursor += 1;
    }
    String thisSuffix = thisString.substring(prefix);
    String theseChars = new String(suffix_chars, offset, suffix);
    assert(thisSuffix.equals(theseChars));
  }
  assert(cp_Utf8_prefix.length == Math.max(0, cp_Utf8_count-2));
  assert(cp_Utf8_suffix.length == Math.max(0, cp_Utf8_count-1));
  assert(cp_Utf8_chars.length == cursor);
  assert(cp_Utf8_big_suffix.length == big_cursor);
  assert(cp_Utf8_big_chars.length == big_cursor);
 

8.2.2. Представление cp_Signature Постоянный Пул

Следующий псевдокод утверждает отношения, как описано выше, между длинами полосы и содержанием, и cp_Signature постоянные элементы пула. (Этот код просто комментирует спецификацию, данную выше; это самостоятельно не добавляет новую информацию к спецификации.)
  int cursor = 0;
  for (int i = 0; i < cp_Signature_count; i++) {
    String sign = cp_Signature[i];
    String form = cp_Signature_form[i];
    int form_ptr = 0;
    int sign_ptr = 0;
    for (; form_ptr < form.length(); form_ptr++) {
      assert(form.charAt(form_ptr) == sign.charAt(sign_ptr));
      sign_ptr += 1;
      if (form.charAt(form_ptr) == 'L') {
        String cls = cp_Class[cursor];
        assert(sign.startsWith(cls, sign_ptr));
        cursor += 1;
        sign_ptr += cls.length();
      }
    }
    assert(sign_ptr == sign.length());
  }
  assert(cp_Signature_form.length == cp_Signature_count);
  assert(cp_Signature_classes.length == cursor);

8.2.3. Представление Байтовых смещений

Следующий псевдокод утверждает отношения, как описано выше, между байтовым смещением и его кодированием в полосе, которой управляет элемент расположения bc_index. (Этот код просто комментирует спецификацию, данную выше; это самостоятельно не добавляет новую информацию к спецификации.)
  // ins_pos is a display of all instruction boundaries
  int[] ins_pos;
  ...
  Arrays.sort(ins_pos);
  assert(ins_pos[0] == 0);
  assert(ins_pos[ins_pos.length-1] == bytecodes.length);
  int regulars = ins_pos.length; //  # instruction boundaries
  ...
  int renumber_bci(int bci) {
    int i = Arrays.binarySearch(ins_pos, bci);
    return (i >= 0) ? i : (i == -1) ? bci : ins_pos.length + bci - (-i-1);
  }
  ...
  for (int bci = -100; bci <= bytecodes.length+100; bci++) {
    int bci_numbering_for_band = renumber_bci(bci);
    int i = Arrays.binarySearch(ins_pos, bci);
    if (i >= 0) {
      assert(ins_pos[i] == bci);
      assert(bci_numbering_for_band < regulars);
      assert(bci_numbering_for_band == i);
    } else if (0 < bci && bci < bytecodes.length) {
      int nexti = (-i-1);  // index of next instruction
      assert(ins_pos[nexti-1] < bci && bci < ins_pos[nexti]);
      int prevRegulars = nexti;
      int prevAll = bci;
      int prevIrregulars = prevAll - prevRegulars;
      assert(bci_numbering_for_band >= regulars);
      assert(bci_numbering_for_band == regulars + prevIrregulars);
    } else {
      // other (random) numbers are unchanged by renumbering
      assert(bci_numbering_for_band >= bytecodes.length ||
             bci_numbering_for_band < 0);
      assert(bci_numbering_for_band == bci);
    }
  }

8.2.4. Представление Предсказуемых Вложенных Имен классов

Следующий псевдокод утверждает отношения, как описано выше, между скорректированным именем вложенного class и предсказуемыми внешними и простыми именами. Отметьте, что ищет литеральные символы '/', и '$' должен быть заменен в реальных реализациях поисками диапазонов символов, связанных с ДОЛЛАРОВЫМИ нетерминалами и НАКЛОННОЙ ЧЕРТОЙ. (Этот код просто комментирует спецификацию, данную выше; это самостоятельно не добавляет новую информацию к спецификации.)
  String bcn, predictableOuter, predictableICName;
  ...
  String name = bcn.substring(bcn.lastIndexOf('/')+1);
  int dollar2 = name.lastIndexOf('$');
  assert(predictableICName == null ||
         (predictableICName.charAt(0) > '9' &&
          predictableICName.indexOf('$') < 0));
  if (predictableICName == null) {
    // bcnCase1 or bcnCase4
    assert(predictableOuter == null);
    assert(dollar2 == -1 ||
           dollar2+1 == name.length() ||
           isDigit(name.charAt(dollar2+1)));
  } else if (predictableOuter == null) {
    // bcnCase2
    assert(name.endsWith("$"+predictableICName));
    int dollar1 = name.substring(0, dollar2).lastIndexOf('$');
    assert(dollar1 >= 0 && dollar1+1 < dollar2);
    assert(isDigitString(name.substring(dollar1+1, dollar2)));
  } else {
    // bcnCase3
    assert(bcn.equals(predictableOuter+"$"+predictableICName));
  }
 

8.3. Приложение: FAQ Проекта

Этот набор часто задаваемых вопросов относительно формата архива Pack200 предназначается, чтобы служить объяснением проекта.

8.3.1. Общие Вопросы

  1. Почему бы не использовать существующий универсальный механизм сжатия, такой как .jar, .zip, или файлы .tar.gz? Во-первых, лучше знать структуру сжатой вещи. Во-вторых, архив zip или фляги сжимается поэлементно не глобально. Это означает, что любой символ, совместно использованный несколькими классами, должен быть упомянут независимо однажды в каждом файле class. В-третьих, структура отдельного файла class является действительно чередованием многих различный вид данных, каждого с их собственной статистикой, которая ограничивает эффективность компрессора единого потока, такого как gzip. Определенное преимущество переупорядочения данных в полосы о факторе два, независимо от качества стандартного компрессора, используемого в качестве постпередачи. От различных специфичных для типа методов перекодирования есть также существенные предельные выгоды. Конечный результат состоит в том, чтобы улучшить фактор сжатия от 2-4X до 7-9X.

  2. Почему эта спецификация настолько сложна? Методы, описанные здесь, являются результатом большого экспериментирования более чем несколько лет. Каждая функция этой спецификации, как думают, способствует в известной мере полному коэффициенту сжатия, достигнутому этой технологией. Авторы были бы счастливы быть показанными сравнительными тестами, что некоторая данная функция может быть опущена без существенной потери производительности сжатия.

    (Множитель производительности сжатия 1.002 или больше для некоторого определенного метода является существенным, потому что такие множители накапливают с готовностью в производительность то уведомление конечных пользователей. Множитель меньше чем 1.0005 является незначащим.)

  3. Формат передачи Pack200 близко связывается к текущему формату файла class. Разве это не будет выходить из моды, как только формат файла class развивается далее? Дальнейшее развитие, вероятно, примет форму новых атрибутов или возможно новых байт-кодов. Язык расположения, определенный Pack200, поддерживает очень широкий диапазон форматов атрибута, включая произвольные смеси байтов и постоянных ссылок пула. Аналогично, представление байт-кода включает операторы escape, которые могут представить произвольные смеси данных и постоянных ссылок пула. Хотя такие конструкции не будут сжиматься так оптимально как функции, для которых непосредственно разрабатывается эта спецификация, кажется, что разумные будущие расширения будут продолжать быть transmittable, не нарушая сжатие текущих функций, и не требуя, чтобы декомпрессоры были обновлены.

  4. Так как Pack200 является алгоритмом сжатия с потерями, он не будет повреждать подписанные файлы JAR? Подписанные файлы JAR содержат безопасный, долго обсуждает bytewise содержание отдельных файлов class. Любое изменение к битам файла class изменит свой хэш-код, производя безвредные изменения Pack200, неотличимых от атак на код программы.

    Pack200, как много других алгоритмов сжатия, позволяет компрессору много степеней свободы в выборе содержания сжатого архива, но никаких степеней свободы в выборе содержания распакованного файла JAR. Учитывая сжатый архив, все совместимые декомпрессоры Pack200 должны произвести те же самые байты файла class, поскольку каждый передал файл class. Эта устойчивость вывода сохраняется для файлов class, даже если файл ресурсов (такой как декларация) изменяет свое содержание. Таким образом, для любого данного файла class, сжатие может быть с потерями, но распаковка каждого файла class должна быть точной полезным способом, определенным спецификацией Pack200.

    Это означает, что компрессор с правильными свойствами устойчивости может использоваться, чтобы произвести подписанный, упакованный JAR, используя эти шаги:

    1. Упакуйте исходный подписанный файл JAR.
    2. Распакуйте это, производя встревожило файлы class.
    3. Оставьте это, гарантируя, что только декларация изменяется.
    4. Перепакуйте это, используя обновленную декларацию.

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

  5. Каково отношение между именами файлов в архивах Pack200 и именами файлов в JAR (или ZIP) дисковые файлы или архивы? Pack200 определяет, что имена файлов передаются как строки Utf8. Так как эти строки предназначаются, чтобы функционировать как имена элементов JAR в функционирующих приложениях Java, строки должны также соответствовать использованию Java, которое также представляет пути, поскольку Utf8 представляет в виде строки в файлах JAR и 16-разрядном Unicode в памяти. Кроме того, в файлах JAR компоненты пути разделяются символом наклонной черты вправо (' / '), а не любым специфичным для системы символом. Это позволяет загрузчикам class легко преобразовывать внутреннее представление имен class (например, "java/lang/Object") к путям (например, "java/lang/Object. class").

    Спецификация Pack200 не диктует интерпретацию строк имени файла относительно любого другого инструмента или операционной системы. Однако, естественное отображение было бы настолько когерентным насколько возможно с использованиями Java.

  6. Каково отношение между датами файла в JAR (или ZIP) дисковые файлы или архивы? Pack200 определяет, что даты файла передаются как 32-разрядные количества секунд относительно основы времени Java (то есть, System.currentTimeMillis, разделенный на одна тысяча). Это обеспечивает абсолютные времена относительно UTC при односекундной гранулярности. Если операционная система обеспечивает более точные времена файла, они должны быть скорректированы к соседней целой секунде перед передачей в архиве Pack200.

    JAR и ZIP хранят даты в локальном формате (то есть,  "YYYY/MM/DD HH:MM:SS") без спецификации часового пояса. Это означает, что преобразование в и с основанных на UTC времен Java требует предположения в часовом поясе, под которым работал компрессор. (Эта проблема не уникальна для Pack200. Это - проблема со всем использованием архивов JAR и ZIP.) Во многих целях стандартное предположение - то, что декомпрессор и компрессор работали в том же самом часовом поясе и во время того же самого ежегодного режима летнего времени. Однако, чтобы обеспечить больше устойчивости во времена, переданные в архивах Pack200, ожидается, что большинство компрессоров и декомпрессоров согласятся использовать UTC в качестве часового пояса, интерпретируя местное время стиля ZIP.

  7. Не формат файла JEFFtm также oprovide class специфичный алгоритм сжатия? Да, Рабочая группа ДЖЕФФА определила стандартный формат файла (ISO/IEC 20970), который позволяет файлам class быть сжатыми приблизительно 50 % и также загруженными непосредственно в память для интерпретирующего выполнения. Как производительность сжатия, это сопоставимо с ВЫКАЧИВАТЬ алгоритмом, используемым в пределах архивов JAR. Pack200 обеспечивает намного большее сжатие. Однако, архивы Pack200 не разрабатываются для прямого выполнения никакой виртуальной машиной. Больший уровень сжатия Pack200 выигрывается по стоимости сложности в неупаковщике, сложность, несовместимая с любым требованием прямой загрузки или выполнения.

  8. Почему не делает Кодирования методом Хаффмана использования Pack200? (Тот же самый вопрос для LZW, или BWT, или перемещение к передней стороне, или любой другой стандартный метод сжатия.) Как простоту и подразделение рабочей силы, Pack200 преднамеренно сосредотачивается на том, чтобы находить и удалять крупномасштабную избыточность, определенную для файлов class. Pack200 производит байтовый вывод, мы надеемся, с четкими образцами и простую статистику алфавита. Это полагается на компрессор постпередачи, чтобы закодировать эти байты в некотором более эффективном совместном использовании строки, нарезанном битом представлении.

    Следующие соображения поддерживают этот проект:

  9. Как эта спецификация справляется с изменениями формата архива? Номера основной версии и номера вспомогательной версии архива Pack200 дают объявление, какая версия этого стандарта была сгенерирована упаковщиком. Из-за гибкости разметок атрибута упаковщики могут иногда представлять новые форматы classfile в старых форматах архива, но более новые форматы архива могут требоваться по причинам функциональности или производительности.

    Реализации неупаковщика строго поощряются поддерживать каждую стандартную версию формата архива, так как есть не всегда выравнивание strong между версиями упаковщика и неупаковщика с обоих концов канала развертывания. Реализации упаковщика поощряются сохранить возможность испустить более старые форматы архива, поддержать максимальную совместимость с неупаковщиками.

    Ссылочная реализация хочет поддерживать обратную совместимость, производя 1.5 формата пакета, если входной архив JAR содержит № 1.6 (или более новый) classfiles. Вообще, это произведет самую старую версию архива, совместимую со всем вводом classfiles. Пустой архив примет значение по умолчанию к самой старой версии архива, которая является 1.5.


Oracle и/или его филиалы Авторское право © 1993, 2012, Oracle и/или его филиалы. Все права защищены.
Свяжитесь с Нами