пятница, 29 апреля 2011 г.

компилятор javac. Как работать с утилитой?

Это инструмент для компиляции джава приложений. С верисии java 6 он также замещает утилиту для работы с аннотациями apt.
javac [ options ] [ sourcefiles ] [ classes ] [ @argfiles ]
Порядок аргументов произвольный.

Чначение аргументов:
options
Опции.
sourcefiles
Один или больше файлов для компиляции (пример такого файла MyClass.java).
classes
Один или больше классов, в которых нужно обработать их аннотации (пример: MyPackage.MyClass).
@argfiles
Один или больше файлов, которые содержат опции и список файлов для компиляции. -J опции нельзя использовать в таких файлах.

Общее описание работы утилиты
Компилировать файлы мы можем двумя способами:
  • если файлов не много, то мы прямо их и указываем в командной строке;
  • если же файлов много, то мы составляем их список в отдельном файле и указываем имя этого файла после символа @.
Чтобы файлы были скомпилированы успешно приложение должно соответсвовать следующим простым правилам:
  1. Именя файлов должны иметь расширение *.java.
  2. Имея файла должно соответвовать имени класса или интерфейса, что находится внутри. Если MyClass.java, то внутри должна быть реализация class MyClass{..} .
  3. Структура каталогов должна соотвествовать обьявленным пакетам внутри файлов. Если код находистя в каталоге /workspace, то и исходный код для класса com.mysoft.mypack.MyClass, дожен находится в /workspace/com/mysoft/mypack/MyClass.java
По специфики работы, байт-код находится в файлах с расширением .class. После компиляции мозможен вариант, что файлов .class будет больше чем файлов исходного кода .java. Причина втом, что компилятор располагает вложенные классы в отдельные файлы, например MyClass$MyInnerClass.class.

Результаты компиляции по-умолчанию будут находится рядом с исходниками, что избежать этого винигрета, нужно пользоваться опцией -d /path/to/classes.

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

Стандартные опции

-Akey[=value]
Опции для передачи в процессор аннотаций. Их не интерпритирует компилятор, но он их предоставляет для процессоров, и отдельные процессоры аннотаций могут их использовать. key это один или составной идентификатор, составной нужно разделять ".".
-cp path or -classpath path
Определяет где искать пользовательские файлы с классами, (не обязательно) процессоры аннотаций и исходники. Этот класспаз перегружает переменную среды CLASSPATH. Если не CLASSPATH, не -cp( -classpath) неопределены, то класспазом считается поточная директория. Если опция -sourcepath неопределена, то класспаз тоже анализируется на наличие исходников. Если -processorpath не определена, то класспаз тоже анализируется на наличие процессоров аннотаций. Как спецудобство, если в элементе класспаза находится * , то это считается, что нужно добавить все архивы с расширением .jar (.JAR) в класспаз. Для примера, каталог foo содрежит a.jar и b.JAR, то элемент класспаза foo/* расширяется до двух элементов - A.jar:b.JAR. Замечание:   взависимости от командного интерпретатора, которым Вы пользуететь в ОС приходится ваилдкасты брать в скобки, пример -- javac -cp "*.jar" MyClass.java.
-Djava.ext.dirs=directories
Перегружает место размещенния библиотек-расширений для данной платформы.
-Djava.endorsed.dirs=directories
Перегружает место размещения endorsed standards path(JAVA_HOME/libs/endorsed).
-d directory
Устанавливается каталог куда будут размещаться файлы с откомпилированными исходниками в байт-код. Директория должна уже существовать на момент компиляции, потому что утилита сама ее не создает. Утилита только создает поддиректории(пакетную структуру). Если не определять эту опции, то откомпилированные файлы появляются рядом со своими исходниками. Note:   директория которая тут определяется автоматически не добавляется в пользовательский класспаз.
-deprecation
Отображает описание каждого использования осужденного класса или метода, а также перегрузку осужденных классов. Без этого ключа утилита javac только список файлов-исходиников в которых случается использование осужденного кода. -deprecation это сокращение для временной(поточная платнформа java6) опции -Xlint:deprecation.
-encoding encoding
Устанавливает кодировку для файлов с исхдниками, например EUC-JP или UTF-8. Если -encoding не определено, то использоуется кодировка, которая стоит по умолчанию для платформы.
-g
Геренирует полную информацию для дебага, включая локальные переменные. По-умолчанию генериться только номера строк и информация в каком исходнике отсчитывать этот номер строки. 
-g:none
Вообще никакой дебажно информациия не сохранять.
-g:{keyword list}
Геренировать только некоторые виды дебага, ключевые слова, по которым определяется вид, перечисляются через запятую.  Возможные ключевые слова:
source
Иформация о исходнике.
lines
Номер строки в исходнике.
vars
Локальные переменные в блоках кода.

-help







Вывести в консоль резюме использования утилиты.

-implicit:{class,none}







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

-nowarn







Отключается вывод предупреждений. Это сокращения для временной для платформы ява 6 опции -Xlint:none.

-proc: {none,only}







Контролирует выполнять ли обработку аннотаций и если какая-то аннотация требует последующую компиляцию. Controls whether annotation processing and/or compilation is done. -proc:none означает выполнить только компиляцию без анализа аннотаций. -proc:only означает, что выполнить только анализ аннотаций, но без либо каких последующих комплиций, основанных на анотациях.

-processor class1[,class2,class3...]







Указываются именна процессоров для аннотаций. Определение этих имен отключает дефолтовые процесс анализа.

-processorpath path







Указываем где искать классы для процессоров аннотаций. Если эта опция не будет указана, а предыдущая будет иметь некий список классов, то поиск будет производиться в класспазе.

-s dir







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

-source release







Опеределяет какой версии платформы код допускается для компиляции. Вот созможные значения:
1.3
Компилатор не поддреживает assertions, generics(н-р: Iterator<String>), а также другие фишки, которые были представлены выше платформы JDK 1.3.
1.4
Этот компилятор уже может принимать код с предоположениями(assertions), они были представлены именно в JDK 1.4.
1.5
Этот помпилятор может принимать generics и другие фишки представленные в JDK 5.
5
Это синоним для 1.5.
1.6
Значение по-умолчанию.This is the default value. Новых фишок для языка в платформе Java SE 6 не было представленно. Хотя теперь ошиобки кодировки будут валиться как ошибки, а не как предупреждения, как было раньше.
6
Это синоним для 1.6.


-sourcepath sourcepath







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

-verbose






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

-version







Вывести информацию о версии.

-X







Вывести информацию про нестандартые опции и выйти.

Кросскомпиляционные опции

По умолчанию классы компилируются в связке в бутсрапными и расширенными библиотеками, которые поставляются вместе с платформой из которой работате утилита javac. Но javac также поддерживает компиляцию с бутсрапными и расширенными библиотеками из дргих платформ(обычно более старых). Для этого нам нужно определить -bootclasspath и -extdirs.
-target version
На основе этой опции классы генерируются для контектной виртуальной машины. Возможные варианты 1.1 1.2 1.3 1.4 1.5 (или 5) и 1.6 (или 6). По-умолчанию -target зависит от значения в -source:
  • Если -source не определен, то значение -target 1.6
  • Если -source 1.2, то значение -target is 1.4
  • Если -source 1.3, то -target is 1.4
  • Для всех других -source, значение -target == значению -source.
-bootclasspath bootclasspath
Кросскомпиляция с бутстрапными библиотеками, которые перечислены через разделитель (:) и могут быть каталогами, JAR-архивами, или ZIP-архивами.
-extdirs directories
Кросскомпиляция с расширенными библиотеками из мест указанных через разделитель.

Нестандартные опции

Эти характерны только для платформы java se 6


-Xbootclasspath/p:path
Добвавить путь вконец списка бутсрапных библиотек.
-Xbootclasspath/a:path
Добвавить путь вначало списка бутсрапных библиотек.
-Xbootclasspath/:path
Полностью перегрузить путь бутсрапных библиотек.
-Xlint
Включить все рекомендованные предупреждения. В этом релизе пратформы все предупреждения рекомендованы.
-Xlint:none
Отключить все предупреждения, которые не установлены в спецификации языка Ява.
-Xlint:-name
Отключить предупреждения типа -Xlint:name. Вот сразу ниже и представлены все эти типы.
-Xlint:unchecked
Детально информировать о непроверенных преобразованиях, которые определены  спецификацией языка.
-Xlint:path
Предупреждать о несуществующих каталогах, которые определены в путях (classpath, sourcepath, etc).
-Xlint:serial
Warn about missing serialVersionUID definitions on serializable classes.
-Xlint:finally
Предупреждать о finally случаях, которые не могут завершиться нормально.
-Xlint:fallthrough
Проверять switch блоки, чтобы кейсы не проваливались на следующие, это возможно если ошибочно не поставлен break после какого-нибудть кейса:
switch (x) {
case 1:
       System.out.println("1");
       //  No  break;  statement here.
case 2:
       System.out.println("2");
}
     
С этим флагом будет выводиться сообщение, что возможно ошибочно не брейкается кейс и рядом номер строки в сорсфайле.
-Xmaxerrs number
Устновить максимальное количество ошибок, которое будет выводиться.
-Xmaxwarns number
Установить макисмальное количество предупреждений, которое будет выводиться в консоль.
-Xstdout filename
Перенаправить поток сообщений компилятора в файл. По умолчанию поток сообщений идет в System.err.
-Xprefer:{newer,source}
Определяет какой файл читать, если найдет и байт-код и исходник типа. Если -Xprefer:newer, то читается то, что последнее было обновлено в файловой системе. Если -Xprefer:source, то читается полюбому исходник. Нужно использовать -Xprefer:source в тех случаях когда нужно быть уверенным, что все процессоры аннотаций могут достичь аннотации, которые обьявлены в соответсвии с политикой хранения исходников.
-Xprint
Выподить текстовое представление определенных типов с целью дебага. Ни обработка аннотаций, ни компиляция при этом не выполняется.
-XprintProcessorInfo
Выводится информация о том, какие процессоры аннотаций были вызваны.
-XprintRounds
Выводится информация о раундах аннотаций при инициализации и последующих обработках.

 -J Опция


-Joption
Передаеются так option в java launcher, который вызвается компилятором javac. К примеру, -J-Xms48m устанавливает стартапный размер памяти в 48 мегабайт. Хоть эта опция и не начинается с -X, это не "стандартная опция" javac. Это просто соглашения как передавать параметры в виртуальную машину, которая вызывает ява-приложения для задач выполняемых утилитой javac, если вызов ява-ланчера должне быть не стандартным. Note:   CLASSPATH, -classpath, -bootclasspath, and -extdirs установка этих параметров для javac, не влияет на приложения, которые обслуживают сам компилятор, а только на то приложение которое им компилируется. Если даже удасться найти дыры и повлиять на него так, то это все-равно очень рисоквано. Если нужно повлиять на компилятор, то нужно посользоваться его опцией -J, а это уже влияение на java launcher, который будет запускать ява-приложения для обеспечения выполнения именно компилятора.

@Аргфайлы
В этих файлах вводят большое количество классов на компиляцию и большое количество аргументов. Пример:
Файл Options:
-d classes
     -g
     -sourcepath /java/pubs/ws/1.3/src/share/classes

Файл Classes:
MyClass1.java
     MyClass2.java
     MyClass3.java

А так производится вызов:
% javac @path1/options @path2/classes 



ANNOTATION PROCESSING
javac обеспечивает прямую поддрежку аннотаций, поэтому нужда в отдельно инструменте, таком как apt, отпала.
API процессоров аннотаций определено в пакетах и их подпакетах javax.annotation.processing и в javax.lang.model.

Осмотр обработки аннотаций

До тех пор пока мы явно не отключим обработку аннотаций опцией -proc:none, компилятор будет искать доступные процессоры. Путь поиска может быть определен опцией -processorpath, если этот путь не определен, то будет происходить поиск в класспазе. Процессоры находятся с помошью файлов поставщика конфигураций сервиса, которые называются
  META-INF/services/javax.annotation.processing.Processor
в соответсвующем архиве. В таких файлах находятся пакетные имена классов(com.site.AnnProcessor1), каждое в отдельной строке, по этим именам компилятор и вытягивает процессоры с поточного архива.  Альтернативой существования предыдущего файла в архиве есть опция -processor, мы можем после нее указать в пакетной последовательности именна классов, которые являются процессорами аннотация и они будут найдены в пути, который был указан в -processorpath. Компилятор сканирует исходники и классы, которые ему передали, собирает информацию о том, какие аннотации встречаются, потом опрашивает процессоры, какие они аннотации обрабатывают, когда находятся соответствия, то аннотации передаются своим процессорам на обработку. Если какой-то процессора потребует, что только он должен обрабатывать конкретные аннотации, то больше эти аннотации не будут проверяться для оставшихся процессоров. Если какой-нибудь процессор сгенерирует новые файлы с исходниками, то потом повторяется цикл с поиском аннотаций в этих новых файлах и опросс процессоров на их обработку. Эти циклы будут повторяться до тех, пор пока все файлы не будут сгенерированны на основании появляющихся аннотациях в новосгенерированных источниках. И в конце-концов, если только не стоит опция -proc:only, компилятор откомпилирует все исходные файлы и получившиеся в результате генерации.

Неявно загруженные исходники

Для комлиции исходников компилятору могут понадобиться дополнительные файлы, которые он неявно загрузит. На данный момент такие файлы не будут обрабатываться на наличие аннотаций в них, а если все-таки аннотации будут встречаться в таких файлах, то компилятор будет генерировать предупреждения. Чтобы подавлять такие предупреждения нужно пользоваться опцией -implicit.
Поиск типов
Часто вовремя компиляции компилятору нужно получить информацию о типе, которого определение не встречается в исходниках, которые были указанны в командной строке. Такая информация нужна о всех классах, интерфейсах, которые используются, а также которые расширяются и реализуются(по всему дереву наследия). Например если наследовать  java.applet.Applet, то автоматически компилятору нужно информация о всех Applet's предках: java.awt.Panel, java.awt.Container, java.awt.Component, и java.lang.Object.
Компилятор ищет такие классы сначала в бутстрапных и расширениях-библиотеках, потом в пользовательском класспазе(это по-умолчанию поточная директория). Пользовательский класспаз может устанавливаться переменной среды ОС CLASSPATH или опцией командной строки -classpath .
Если указана опция -sourcepath, то компилятор там ищет исходники; если не указана, то исходники ищутся в класспазе.
Можно указать дргие бустрапные библиотеки и расширения с помошью опций -bootclasspath and -extdirs, это кросскомпиляционные опции.
Успешный поиск типа, может найти либо байт-код, либо исходник, либо то и другое.  Если найдены оба, то опция -Xprefer инструктирует компилятор, откуда брать информацию о типе. Вожножные варианты опции: newer - возьмется из того, кто был изменен последний; source - возьметрся исходник. По-умолчанию компилятор ведет себя, как в случае newer.
В допронение к получению информации о типе из исходника, компилятор откомпилирует этот исходник. Хотя на эту политику мы можем влиять опцией -implicit. Если у нее значение none байт-код(*.class-файлы)-файлы не будут создаваться(компилироваться). Если class -- то будут.
Компилятор может не понять нужно ли ему искать дополнительные классы для получения информации о типах, если в исходнике находятся аннотации. Поэтому если какой-нибудь файл-исходник был подхвачен, для получения информации о типе, а там находится аннотация, то будет сгенерировано предупреждение, потомучто файл откомпилируется без учета обработки аннотации. Чтобы не видеть подобных сообщений нужно либо указать этот исходник в командной строке явно под компиляцию, либо использовать опцию -implicit, в которой указать нужно ли комплилировать такие исходники.

API для использования утилиты-компилятора

javac поддерживает новые Java Compiler API определены классами и интерфейсами пакета javax.tools.

Example

To perform a compilation using arguments as you would give on the command line, you can use the following:
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
int rc = javac.run(null, null, null, args);
      
This will write any diagnostics to the standard output stream, and return the exit code that javac would give when invoked from the command line.
You can use other methods on the javax.tools.JavaCompiler interface to handle diagnostics, control where files are read from and written to, and so on.

Old Interface

Note:   This API is retained for backwards compatibility only; all new code should use the Java Compiler API, described above.
The com.sun.tools.javac.Main class provides two static methods to invoke the compiler from a program:
public static int compile(String[] args);
public static int compile(String[] args, PrintWriter out);
      
The args parameter represents any of the command line arguments that would normally be passed to the javac program and are outlined in the above Synopsis section.
The out parameter indicates where the compiler's diagnostic output is directed.
The return value is equivalent to the exit value from javac.
Note that all other classes and methods found in a package whose name starts with com.sun.tools.javac (informally known as sub-packages of com.sun.tools.javac) are strictly internal and subject to change at any time.

Комментариев нет:

Отправить комментарий