Spec-Zone .ru
спецификации, руководства, описания, API
|
Эта глава включает следующие темы:
Чтобы увеличить сервер и сетевую доступность и пропускную способность, два новых формата сжатия доступны развертыванию Java приложений и апплетов: gzip и Pack200.
С обоими методами сжатые файлы JAR передаются по сети, и приложение получения распаковывает и восстанавливает их.
HTTP 1.1 (RFC 2616) протокол обсуждает сжатие HTTP. Сжатие HTTP позволяет файлам JAR приложений быть развернутыми как сжатые файлы JAR. Поддерживаемые методы сжатия являются gzip, сжатием, выкачивают.
С версии 5.0 SDK/JRE сжатие HTTP реализуется в Java веб-Запуск и Плагин Java в соответствии с RFC 2616. Поддерживаемые методы являются gzip и pack200-gzip.
Запрашивающее приложение отправляет запрос HTTP серверу. У запроса HTTP есть многократные поля. Принятый закодированный (AE) поле устанавливается в pack200-gzip
или gzip
, указание к серверу, что приложение может обработать pack200-gzip
или gzip
формат.
Реализация сервера будет искать требуемый файл JAR с .pack.gz
или .gz
расширение файла и отвечает назад расположенным файлом. Сервер установит Кодирование контента заголовка ответа (CE) поле к pack200-gzip
, gzip
, или НУЛЬ в зависимости от типа файла, который отправляется, и дополнительно может установить Тип контента (CT) в application/Java-archive. Поэтому, осматривая поле CE, запрашивающее приложение может применить соответствующее преобразование, чтобы восстановить исходный файл JAR.
Вышеупомянутое может быть достигнуто, используя простой сервлет или модуль сервера с любым HTTP 1.1 совместимых веб-сервера. Сжатие файлов на лету ухудшит производительность сервера, особенно с Pack200, и поэтому не рекомендуемое.
Демонстрационный Сервлет Tomcat:
/** * A simple HTTP Compression Servlet */ import java.util.*; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.zip.*; import java.net.*; /** * The servlet class. */ public class ContentType extends HttpServlet { private static final String JNLP_MIME_TYPE = "application/x-java-jnlp-file"; private static final String JAR_MIME_TYPE = "application/x-java-archive"; private static final String PACK200_MIME_TYPE = "application/x-java-pack200"; // HTTP Compression RFC 2616 : Standard headers public static final String ACCEPT_ENCODING = "accept-encoding"; public static final String CONTENT_TYPE = "content-type"; public static final String CONTENT_ENCODING = "content-encoding"; // HTTP Compression RFC 2616 : Standard header for HTTP/Pack200 Compression public static final String GZIP_ENCODING = "gzip"; public static final String PACK200_GZIP_ENCODING = "pack200-gzip"; private void sendHtml(HttpServletResponse response, String s) throws IOException { PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>ContentType</title>"); out.println("</head>"); out.println("<body>"); out.println(s); out.println("</body>"); out.println("</html>"); } /* * Copy the inputStream to output , */ private void sendOut(InputStream in, OutputStream ostream) throws IOException { byte buf[] = new byte[8192]; int n = in.read(buf); while (n > 0 ) { ostream.write(buf,0,n); n = in.read(buf); } ostream.close(); in.close(); } boolean doFile(String name, HttpServletResponse response) { File f = new File(name); if (f.exists()) { getServletContext().log("Found file " + name); response.setContentLength(Integer.parseInt( Long.toString(f.length()))); response.setDateHeader("Last-Modified",f.lastModified()); return true; } getServletContext().log("File not found " + name); return false; } /** Called when someone accesses the servlet. */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String encoding = request.getHeader(ACCEPT_ENCODING); String pathInfo = request.getPathInfo(); String pathInfoEx = request.getPathTranslated(); String contentType = request.getContentType(); StringBuffer requestURL = request.getRequestURL(); String requestName = pathInfo; ServletContext sc = getServletContext(); sc.log("----------------------------"); sc.log("pathInfo="+pathInfo); sc.log("pathInfoEx="+pathInfoEx); sc.log("Accept-Encoding="+encoding); sc.log("Content-Type="+contentType); sc.log("requestURL="+requestURL); if (pathInfoEx == null) { response.sendError(response.SC_NOT_FOUND); return; } String outFile = pathInfo; boolean found = false; String contentEncoding = null; // Pack200 Compression if (encoding != null && contentType != null && contentType.compareTo(JAR_MIME_TYPE) == 0 && encoding.toLowerCase().indexOf(PACK200_GZIP_ENCODING) > -1){ contentEncoding = PACK200_GZIP_ENCODING; if (doFile(pathInfoEx.concat(".pack.gz"),response)) { outFile = pathInfo.concat(".pack.gz") ; found = true; } else { // Pack/Compress and transmit, not very efficient. found = false; } } // HTTP Compression if (found == false && encoding != null && contentType != null && contentType.compareTo(JAR_MIME_TYPE) == 0 && encoding.toLowerCase().indexOf("gzip") > -1) { contentEncoding = GZIP_ENCODING; if (doFile(pathInfoEx.concat(".gz"),response)) { outFile = pathInfo.concat(".gz"); found = true; } } // No Compression if (found == false) { // just send the file contentEncoding = null; sc.log(CONTENT_ENCODING + "=" + "null"); doFile(pathInfoEx,response); outFile = pathInfo; } response.setHeader(CONTENT_ENCODING, contentEncoding); sc.log(CONTENT_ENCODING + "=" + contentEncoding + " : outFile="+outFile); if (sc.getMimeType(pathInfo) != null) { response.setContentType(sc.getMimeType(pathInfo)); } InputStream in = sc.getResourceAsStream(outFile); OutputStream out = response.getOutputStream(); if (in != null) { try { sendOut(in,out); } catch (IOException ioe) { if (ioe.getMessage().compareTo("Broken pipe") == 0) { sc.log("Broken Pipe while writing"); return; } else throw ioe; } } else response.sendError(response.SC_NOT_FOUND); } } |
Pack200 сжимает большие файлы очень эффективно, в зависимости от плотности и размера файлов класса в файле JAR. Можно ожидать сжатие к 1/9 размер файла JAR, если это будет содержать только файлы класса и будет в порядке нескольких Мбайт.
Используя ту же самую флягу в предыдущем примере:
Notepad.jar 46.25 Кбит
Notepad.jar.pack.gz 22.58 Кбита
В этом случае та же самая фляга может быть уменьшена на 50 %.
Пожалуйста, отметьте: подписывая большие фляги, шаг 5 может перестать работать с Ошибкой Безопасности â , вероятной причиной является ошибка
Pack200 работает наиболее эффективно над файлами класса Java. Это использует несколько методов, чтобы эффективно уменьшить размер файлов JAR:
Pack200 может использоваться при использовании Интерфейсов командной строки pack200 (1), unpack200 (1) в каталоге bin Вашего SDK или каталога JRE.
Интерфейсы Pack200 могут также вызванный программно от Java, пожалуйста, обратитесь к API и ссылкам JavaDoc на Java.util.jar. Pack200.
1. Рассмотрите размер файла JAR, содержание файла JAR, и пропускную способность Вашей целевой аудитории.
Все эти факторы играют в выбор метода сжатия. unpack200 разрабатывается, чтобы быть настолько эффективным насколько возможно, и он занимает время, чтобы восстановить исходный файл. Если у Вас есть большие файлы JAR (2 Мбайта или больше) состоявший главным образом из файлов класса, Pack200 является привилегированным методом сжатия. Если у Вас есть большие файлы JAR, которые состоят из файлов ресурсов (JPEG, ДЖИФ, данные, и т.д.), то gzip является привилегированным методом сжатия.
2. Сегментация Pack200.
Pack200 загружает весь упакованный файл в память. Однако, когда целевые системы являются памятью и ограниченным ресурсом, устанавливая Pack200.Packer.SEGMENT_LIMIT
к нижнему значению, уменьшит требования к памяти во время упаковки и распаковки. Pack200.Packer.SEGMENT_LIMIT=-1
вынудит один сегмент быть сгенерированным, который будет эффектом в сокращении размера, но потребует, чтобы намного больший Java свалил в кучу упаковку и распаковку системы. Отметьте, что несколько из этих упакованных сегментов могут быть связаны, чтобы произвести единственный упакованный файл.
3. Подписание файлов JAR.
Pack200 перестраивает содержание результирующего файла JAR. jarsigner хеширует содержание файла класса и хранит хеш в зашифрованном обзоре в декларации. Когда неупаковщик будет работать на упакованном упакованном, содержание классов будет перестроено и таким образом лишит законной силы подпись. Поэтому, файл JAR должен быть нормализован, сначала используя pack200 и unpack200, и после того подписан.
(Вот то, почему это работает: Любое переупорядочение упаковщика делает любых classfile структур, идемпотент, таким образом, вторая упаковка не изменяет упорядочивания, произведенные первой упаковкой. Кроме того, неупаковщику гарантирует JSR 200 спецификаций, чтобы произвести определенное изображение bytewise для любого данного упорядочивания передачи элементов архива.)
Предположите, что Вы хотите использовать HelloWorld.jar.
Шаг 1: Перепакуйте файл, чтобы нормализовать флягу, перепаковывая вызовы упаковщик, и распаковывает файл за один шаг. % pack200 --repack HelloWorld.jar Шаг 2: Подпишите флягу после того, как мы нормализуем использование, перепаковывают. % jarsigner -keystore myKeystore HelloWorld.jar ksrini Проверьте справедливую флягу со знаком, чтобы гарантировать работавшее подписание. % jarsigner -verify HelloWorld.jar Гарантируйте, что фляга все еще работает. % Java -jar HelloWorld.jar Шаг 3: Теперь мы упаковываем файл % pack200 HelloWorld.jar.pack.gz HelloWorld.jar Шаг 4: Распакуйте файл % unpack200 HelloWorld.jar.pack.gz HelloT1.jar Шаг 5: Проверьте флягу % jarsigner -verify HelloT1.jar //Протестируйте флягу... % Java -jar HelloT1.jar После проверки сжатый файл пакета может быть развернут HelloWorld.jar.pack.gz. |
4. Методы сокращения:
Pack200.Packer.MODIFICATION_TIME="LATEST"
. Это позволит одному времени изменения быть переданным в файле пакета для каждого сегмента. Последнее время будет последним временем любой записи в пределах того сегмента. Например:
pack200 --modification-time=latest --deflate-hint="true" tools-md.jar.pack.gz tools.jar
Отметьте: вышеупомянутая оптимизация приведет к лучшим результатам с файлом JAR, содержащим тысячи записей.
Pack200.Packer.STRIP_DEBUG=true.
Это обычно уменьшает упакованный файл приблизительно на 10 %. Пример:
pack200 --strip-debug tools-stripped.jar.pack.gz tools.jar
5. Обработка неизвестных атрибутов:
Соглашения Pack200 со стандартными атрибутами, определенными Спецификацией виртуальной машины Java, однако компиляторы, являются бесплатными представить пользовательские атрибуты. Когда такие атрибуты присутствуют, по умолчанию, Pack200 проходит через класс, испуская предупреждающее сообщение. Они "проходили" через файлы класса, может способствовать чрезмерному увеличению размера упакованных файлов. Если неизвестные атрибуты распространены в классах файла JAR, это может привести к очень большому чрезмерному увеличению размера упакованного вывода. В таких случаях рассмотрите следующие стратегии:
Разделите атрибут, если атрибут , как считают, избыточен во время выполнения, это может быть достигнуто, устанавливая свойство Pack200. Упаковщик.UNKNOWN_ATTRIBUTE=STRIP or
pack200 --unknown-attribute=strip foo.pack.gz foo.jar
Если атрибуты требуются во время выполнения, и они действительно способствуют инфляции, то идентифицируют атрибут из предупреждающего сообщения и применяют подходящее расположение для них, как описано в Pack200 JSR 200 спецификаций., и ссылочный раздел API Java для Pack200. Упаковщик.
Через его возможное, что компилятор мог определить атрибут, не реализованный в спецификации расположения Pack200, и может заставить Пакера неправильно функционировать в таких случаях весь файл (ы) класса, можно "пройти", как будто это было ресурсом на основании своего имени и может быть определено следующим образом:
pack200 --pass-file="com/acme/foo/bar/baz.class" foo.pack.gz foo.jar
или весь каталог и его содержание,
pack200 --pass-file="com/acme/foo/bar/" foo.pack.gz foo.jar
6. Установщики:
Можно хотеть использовать в своих интересах технологию Pack200 в своей программе установки, посредством чего флягам продукта, возможно, понадобится к сжатому использованию Pack200 и распакованный во время установки. Если JRE или SDK связываются в установке, Вы свободны использовать unpack200 (Unix) или unpack200.exe (Windows) в каталоге 'мусорного ведра' распределения, эта реализация является чистым приложением C++, не требующим, чтобы никакая Среда выполнения Java присутствовала для этого, чтобы работать.
Windows: Установщики могут использовать лучший алгоритм чем тот в GZIP, чтобы сжать записи в таких случаях, каждый получит лучшее сжатие, используя внутреннее сжатие Установщика, при использовании pack200 следующим образом:
pack200 --no-gzip foo.jar.pack foo.jar
Это будет препятствовать тому, чтобы выходной файл был сжатым gzip.
unpack200 является Windows Console application, то есть он выведет на экран окно MS-DOS во время установки, чтобы подавить это, можно использовать средство запуска с WinMain, который подавит это окно, как показано ниже.
Пример кода:
#include "windows.h" #include <stdio.h> int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(pi)); //Test //lpCmdLine = "c:/build/windows-i586/bin/unpack200 -l c:/Temp/log c:/Temp/rt.pack c:/Temp/rt.jar"; int ret = CreateProcess(NULL, /* Exec. name */ lpCmdLine, /* cmd line */ NULL, /* proc. sec. attr. */ NULL, /* thread sec. attr */ TRUE, /* inherit file handle */ CREATE_NO_WINDOW | DETACHED_PROCESS, /* detach the process/suppress console */ NULL, /* env block */ NULL, /* inherit cwd */ &si, /* startup info */ &pi); /* process info */ if ( ret == 0) ExitProcess(255); // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); DWORD exit_val; // Be conservative and return if (GetExitCodeProcess(pi.hProcess, &exit_val) == 0) ExitProcess(255); ExitProcess(exit_val); // Return the error code of the child process return -1; } |
Требуется, что все файлы JAR, упаковали и распаковали, быть протестированными на правильность с Вашими приложениями тестируют спецификаторы. При использовании интерфейса командной строки pack200
, выходной файл будет сжат, используя gzip
со значениями по умолчанию. Пользователь может создать простой файл пакета и использование сжатия gzip
с определенными пользователем опциями или использующий некоторый другой компрессор.
Для получения дополнительной информации см. pack200
и unpack200
в Инструментах Развертывания Java.
В Java SE 6, был обновлен формат файла класса Java. Для получения дополнительной информации см.
Чтобы сохранить изменения минимальными и без шва для пользователей, упаковщик генерирует соответственно имеющие версию файлы пакета, основанные на версии входных файлов класса.
Также, чтобы поддержать обратную совместимость, если входные файлы JAR исключительно состоят из JDK 1.5 или более старых файлов класса, 1.5 совместимых файла пакета производятся. Иначе Java SE 6 совместимых pack200 файлов производится. Для получения дополнительной информации отошлите страницу справочника Pack200.