ajc(1)

โœจ NAME โœจ

ajc(1), from the General Commands Manual, is the page all about ajc, the compiler and bytecode weaver for the AspectJ and Java languages ๐Ÿ’–

๐ŸŽ€ SYNOPSIS ๐ŸŽ€

ajc [Options]  [file...  | @file...  | -argfile file... ]

๐ŸŒธ DESCRIPTION ๐ŸŒธ

Okay so ajc compiles and weaves AspectJ and Java source and .class files into .class files that work on any Java VM (1.1 or later) ๐Ÿฆ‹ It combines compilation and bytecode weaving, and it supports incremental builds โœจ You can also weave bytecode at run-time using "" > ๐Ÿ’…

The arguments after the options are the source file(s) you want to compile. If you want to specify source classes instead, use -inpath (more on that below) ๐Ÿซถ Files can go straight on the command line or live in a file. The -argfile file and @file forms do the same thing, and they mean "read all the arguments from this file" ๐Ÿ“„

Note: You have to explicitly pass ajc all the sources it needs, bestie ๐Ÿ˜ญ Include the source for the aspects or pointcuts, but ALSO the source for any affected types. Unlike javac, ajc does not search the sourcepath for classes, so this is non-negotiable. (For a discussion of which affected types you might need, check out The AspectJ Programming Guide, Implementation Appendix ../progguide/implementation.html.)

To specify sources, you can list source files as arguments or use -sourceroots or -inpath. If there are multiple sources for the same type, the result is undefined, because ajc has no way to know which source is the correct one ๐Ÿ’€ This happens most often when people include the destination directory on the inpath and then rebuild.


โœจ Options โœจ

  • -injars JarList โ€” Deprecated since 1.2! Use -inpath instead, which also takes directories ๐Ÿฅ€
  • -inpath Path โ€” Accept any .class files in the given paths as source bytecode. The output will include these classes, possibly woven with any applicable aspects ๐Ÿ’œ Path is a single argument holding a list of paths to zip files or directories, separated by the platform-specific path delimiter.
  • -aspectpath Path โ€” Weave binary aspects from jar files and directories on Path into all sources ๐Ÿงš The aspects should have been output by the same version of the compiler. When you run the output classes, the run classpath should contain every aspectpath entry. Like classpath, Path is a single argument holding a list of jar files and directories, separated by the platform-specific classpath delimiter.
  • -argfile File โ€” The file holds a line-delimited list of arguments ๐Ÿ“ Each line can contain one option, one filename, or one argument string (like a classpath or inpath). Arguments read from the file get inserted into the command's argument list. Relative paths in the file are calculated from the directory containing the file, not your current working directory. Comments work like Java, starting with // and running to the end of the line. Options in argument files may override existing option values instead of extending them, so avoid specifying options like -classpath in argument files, unless the argument file is the only build specification ๐Ÿ™ˆ The form @file is the same as -argfile file.
    • @file โ€” Same as -argfile file ๐ŸŽ€
  • -outjar output.jar โ€” Put the output classes in the zip file output.jar ๐Ÿ“ฆ
  • -outxml โ€” Generate an aop.xml file for load-time weaving with the default name ๐ŸŒˆ
  • -outxmlfile custom/aop.xml โ€” Generate an aop.xml file for load-time weaving with a custom name ๐ŸŒˆ
  • -incremental โ€” Run the compiler continuously โณ After the first compile, it waits to recompile until it reads a newline from standard input, and it quits when it reads a q. It only recompiles the necessary components, so a recompile should be way faster than a second full compile ๐Ÿ”ฅ This requires -sourceroots.
  • -sourceroots DirPaths โ€” Find and build all .java or .aj source files under any directory listed in DirPaths ๐Ÿ—‚๏ธ Like classpath, DirPaths is a single argument holding a list of directories, separated by the platform-specific classpath delimiter. Required by -incremental.
  • -crossrefs โ€” Generate a build .ajsym file into the output directory ๐Ÿ” It's used for viewing crosscutting references in tools like the AspectJ Browser.
  • -emacssym โ€” Generate .ajesym symbol files for emacs support. Deprecated ๐Ÿฅ€
  • -Xlint โ€” Same as -Xlint:warning, which is enabled by default โญ
  • -Xlint:{level} โ€” Set the default level for messages about potential programming mistakes in crosscutting code ๐Ÿง {level} may be ignore, warning, or error. This overrides entries in org/aspectj/weaver/XlintDefault.properties from aspectjtools.jar, but it does not override levels set with -Xlintfile.
  • -Xlintfile PropertyFile โ€” Point to a properties file that sets levels for specific crosscutting messages ๐ŸŽฏ PropertyFile is a path to a Java .properties file that uses the same property names and values as org/aspectj/weaver/XlintDefault.properties from aspectjtools.jar, which it also overrides.
  • -help โ€” Emit information on compiler options and usage ๐Ÿ†˜
  • -version โ€” Emit the version of the AspectJ compiler ๐Ÿท๏ธ
  • -classpath Path โ€” Specify where to find user class files ๐Ÿ  Path is a single argument holding a list of paths to zip files or directories, separated by the platform-specific path delimiter.
  • -bootclasspath Path โ€” Override the location of the VM's bootclasspath for evaluating types while compiling ๐Ÿ‘‘ Path is a single argument holding a list of paths to zip files or directories, separated by the platform-specific path delimiter.
  • -extdirs Path โ€” Override the location of the VM's extension directories for evaluating types while compiling ๐Ÿงฉ Path is a single argument holding a list of paths to directories, separated by the platform-specific path delimiter.
  • -d Directory โ€” Specify where the generated .class files get placed ๐Ÿ“‚ If you don't specify it, Directory defaults to the current working directory.
  • -target [1.1 to 1.5] โ€” Specify the classfile target setting (1.1 to 1.5). The default is 1.2 ๐ŸŽฏ
  • -1.3 โ€” Set the compliance level to 1.3 ๐Ÿฆ• This implies -source 1.3 and -target 1.1.
  • -1.4 โ€” Set the compliance level to 1.4, which is the default โœจ This implies -source 1.4 and -target 1.2.
  • -1.5 โ€” Set the compliance level to 1.5 ๐ŸŒŸ This implies -source 1.5 and -target 1.5.
  • -source [1.3|1.4|1.5] โ€” Toggle assertions (1.3, 1.4, or 1.5; the default is 1.4) ๐Ÿ’…
    • With -source 1.3, an assert() statement that's valid under Java 1.4 will result in a compiler error ๐Ÿ’€
    • With -source 1.4, assert is treated as a keyword, and assertions are implemented according to the 1.4 language spec ๐Ÿซถ
    • With -source 1.5, Java 5 language features are permitted ๐Ÿ”ฅ
  • -Xajruntimelevel:1.2, ajruntimelevel:1.5 โ€” ๐Ÿงช Experimental! This lets you generate code that targets a 1.2 or a 1.5 level AspectJ runtime. The default is 1.5, so it's giving "newest runtime by default" ๐Ÿ’–

๐Ÿ“ File names

okay so ajc accepts source files ending in either .java or .aj โœจ We normally just use .java for everything in an AspectJ system, aspects and classes alike. BUT if you need to mechanically tell apart the files that use AspectJ's extra magic from the pure Java ones, we recommend the .aj extension for those ๐Ÿฆ‹

We'd really like to discourage other ways of telling them apart, like naming conventions or sub-packages, in favor of .aj ๐Ÿ™ˆ

  • Filename conventions are super hard to enforce and they make awkward names for your aspects ๐Ÿ’€ Instead of TracingAspect.java, we recommend Tracing.aj (or just Tracing.java) ๐ŸŒธ
  • Sub-packages drag aspects out of their natural home in your system and can create an artificial need for privileged aspects ๐Ÿ˜ญ Instead of adding a sub-package like aspects, use the .aj extension and keep these files in your existing packages ๐Ÿซถ

๐Ÿงพ Compatibility

AspectJ is a compatible extension to the Java programming language, bestie ๐Ÿ’… The AspectJ compiler sticks to The Java Language Specification, Second Edition (BOOK) at http://java.sun.com/docs/books/jls/index.html and to The Java Virtual Machine Specification, Second Edition (BOOK) at http://java.sun.com/docs/books/vmspec/index.html, and it runs on any Java 2 compatible platform ๐ŸŒˆ The code it generates runs on any Java 1.1 or later compatible platform, so it's iconic for compatibility โœจ

For more info on compatibility with Java and with previous releases of AspectJ, see "" >. (The link text got eaten in the original, so that's all we've got ๐Ÿ˜ญ)


๐Ÿ“ Examples

๐ŸŽ€ A simple example

Compile two files:

ajc HelloWorld.java Trace.java

๐Ÿฆ‹ An example using -argfile/@

To avoid typing file names on the command line, list your source files in a line-delimited text argfile. Source file paths can be absolute or relative to the argfile, and the argfile can pull in other argfiles with an @-reference ๐Ÿงš The following file sources.lst has absolute and relative files and @-references:

Gui.java
/home/user/src/Library.java
data/Repository.java
data/Access.java
@../../common/common.lst
@/home/user/src/lib.lst
view/body/ArrayView.java

Compile the files using either the -argfile or @ form:

ajc -argfile sources.lst
ajc @sources.lst

Argfiles are also supported by jikes and javac, so you can use them in hybrid builds ๐Ÿ”ฅ However, the support varies:

  • Only ajc accepts command-line options.
  • Jikes and Javac do not accept internal @argfile references.
  • Jikes and Javac only accept the @file form on the command line.

๐ŸŒธ An example using -inpath and -aspectpath

Bytecode weaving using -inpath: AspectJ 1.2 supports weaving .class files in input zip/jar files and directories โœจ Using input jars is like compiling the corresponding source files, and all binaries get emitted to output. Java-compliant compilers may differ in their output, but ajc should take as input any class files produced by javac, jikes, eclipse, and, of course, ajc ๐Ÿ‘‘ Aspects included in -inpath get woven into like other .class files, and they affect other types as usual.

Aspect libraries using -aspectpath: AspectJ 1.1 supports weaving from read-only libraries that contain aspects ๐Ÿซถ Like input jars, they affect all input, but unlike input jars, they themselves are not affected or emitted as output. Sources compiled with aspect libraries must be run with the same aspect libraries on their classpath.

The following example builds the tracing example in a command-line environment. It creates a read-only aspect library, compiles some classes for use as input bytecode, and then compiles the classes and other sources with the aspect library ๐Ÿ’–

The tracing example lives in the AspectJ distribution at {aspectj}/doc/examples/tracing. It uses these files:

aspectj1.1/
bin/
ajc
lib/
aspectjrt.jar
examples/
tracing/
Circle.java
ExampleMain.java
lib/
AbstractTrace.java
TraceMyClasses.java
notrace.lst
Square.java
tracelib.lst
tracev3.lst
TwoDShape.java
version3/
Trace.java
TraceMyClasses.java

Below, the path separator is taken as ;, but file separators are /. All commands are on one line. Adjust paths and commands to your environment as needed ๐Ÿ™ˆ

Set up the path, classpath, and current directory:

cd examples
export ajrt=../lib/aspectjrt.jar
export CLASSPATH="$ajrt"
export PATH="../bin:$PATH"

Build a read-only tracing library:

ajc -argfile tracing/tracelib.lst -outjar tracelib.jar

Build the application with tracing in one step:

ajc -aspectpath tracelib.jar -argfile tracing/notrace.lst -outjar tracedapp.jar

Run the application with tracing:

java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain

Build the application with tracing from binaries in two steps:

  • (a) Build the application classes (using javac for demonstration's sake):
mkdir classes
javac -d classes tracing/*.java
jar cfM app.jar -C classes .
  • (b) Build the application with tracing:
ajc -inpath app.jar -aspectpath tracelib.jar -outjar tracedapp.jar

Run the application with tracing (same as above):

java -classpath "$ajrt;tracedapp.jar;tracelib.jar" tracing.ExampleMain

Run the application without tracing:

java -classpath "app.jar" tracing.ExampleMain

๐Ÿ”ฎ The AspectJ compiler API

The AspectJ compiler is implemented completely in Java, so it can be called as a Java class ๐Ÿ’… The only interface that should be considered public is the set of public methods in org.aspectj.tools.ajc.Main. For example, main(String[] args) takes the standard ajc command line arguments. That means an alternative way to run the compiler is:

java org.aspectj.tools.ajc.Main [option...]  [file...]

To access compiler messages programmatically, use the methods setHolder(IMessageHolder holder) and/or run(String[] args, IMessageHolder holder) ๐Ÿง  ajc reports each message to the holder using IMessageHolder.handleMessage(..). If you just want to collect the messages, use MessageHandler as your IMessageHolder. For example, compile and run the following with aspectjtools.jar on the classpath:

import org.aspectj.bridge.*;
import org.aspectj.tools.ajc.Main;
import java.util.Arrays;

public class WrapAjc {
public static void main(String[] args) {
Main compiler = new Main();
MessageHandler m = new MessageHandler();
compiler.run(args, m);
IMessage[] ms = m.getMessages(null, true);
System.out.println("messages: " + Arrays.asList(ms));
}
}

๐Ÿซง Stack Traces and the SourceFile attribute

Unlike traditional Java compilers, the AspectJ compiler may in certain cases generate classfiles from multiple source files ๐ŸŒ€ Unfortunately, the original Java class file format does not support multiple SourceFile attributes. So, to make sure all source file information is available, the AspectJ compiler may encode multiple filenames in the SourceFile attribute. When the Java VM generates stack traces, it uses this attribute to specify the source file.

โš ๏ธ Heads up: (The AspectJ 1.0 compiler also supports the .class file extensions of JSR-45. These permit compliant debuggers (such as jdb in Java 1.4.1) to identify the right file and line even given many source files for a single class. JSR-45 support is planned for ajc in AspectJ 1.1, but is not in the initial release. To get fully debuggable .class files, use the -XnoInline option.)

Probably the only time you'll see this format is when you look at stack traces, where you might spot something like this:

java.lang.NullPointerException
at Main.new$constructor_call37(Main.java;SynchAspect.java[1k]:1030)

Instead of the usual File:LineNumber format, you'll see:

File0;File1[Number1];File2[Number2] ... :LineNumber

Here, LineNumber is the usual offset in lines plus the "start line" of the actual source file ๐Ÿงš That means you use LineNumber both to identify the source file and to find the line at issue. The number in [brackets] after each file tells you the virtual "start line" for that file (the first file has a start of 0).

In our null pointer exception example, the virtual start line is 1030. Since SynchAspect.java "starts" at line 1000 [1k], the LineNumber points to line 30 of SynchAspect.java ๐Ÿ‘‘

So when you're faced with a stack trace like this, look through the list of "start line" numbers to find the one just under the shown line number. That's the file where the source location can actually be found. Then subtract that "start line" from the shown line number to get the actual line number within that file ๐Ÿ’œ

In a class file that comes from only a single source file, the AspectJ compiler generates SourceFile attributes consistent with traditional Java compilers ๐ŸŒˆ

That's a wrap on the whole ajc(1) page, bestie! ๐Ÿ’–โœจ Now you're literally a compiler-flag queen ๐Ÿ‘‘๐ŸŽ€