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-inpathinstead, which also takes directories ๐ฅ-inpath Pathโ Accept any.classfiles in the given paths as source bytecode. The output will include these classes, possibly woven with any applicable aspects ๐Pathis 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 onPathinto 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,Pathis 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-classpathin argument files, unless the argument file is the only build specification ๐ The form@fileis the same as-argfile file.@fileโ Same as-argfile file๐
-outjar output.jarโ Put the output classes in the zip fileoutput.jar๐ฆ-outxmlโ Generate anaop.xmlfile for load-time weaving with the default name ๐-outxmlfile custom/aop.xmlโ Generate anaop.xmlfile 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 aq. 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.javaor.ajsource files under any directory listed inDirPaths๐๏ธ Like classpath,DirPathsis a single argument holding a list of directories, separated by the platform-specific classpath delimiter. Required by-incremental.-crossrefsโ Generate a build.ajsymfile into the output directory ๐ It's used for viewing crosscutting references in tools like the AspectJ Browser.-emacssymโ Generate.ajesymsymbol 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 beignore,warning, orerror. This overrides entries inorg/aspectj/weaver/XlintDefault.propertiesfromaspectjtools.jar, but it does not override levels set with-Xlintfile.-Xlintfile PropertyFileโ Point to a properties file that sets levels for specific crosscutting messages ๐ฏPropertyFileis a path to a Java.propertiesfile that uses the same property names and values asorg/aspectj/weaver/XlintDefault.propertiesfromaspectjtools.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 ๐Pathis 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 ๐Pathis 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 ๐งฉPathis a single argument holding a list of paths to directories, separated by the platform-specific path delimiter.-d Directoryโ Specify where the generated.classfiles get placed ๐ If you don't specify it,Directorydefaults 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.3and-target 1.1.-1.4โ Set the compliance level to 1.4, which is the default โจ This implies-source 1.4and-target 1.2.-1.5โ Set the compliance level to 1.5 ๐ This implies-source 1.5and-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, anassert()statement that's valid under Java 1.4 will result in a compiler error ๐ - With
-source 1.4,assertis 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 ๐ฅ
- With
-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 recommendTracing.aj(or justTracing.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
.ajextension 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
@argfilereferences. - Jikes and Javac only accept the
@fileform 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 ๐๐
๐ฆ where this page comes from
- debian bookworm: aspectj 1.9.5-2 ยท EPL-1.0
- debian trixie: aspectj 1.9.6-1 ยท EPL-1.0
- ubuntu jammy: aspectj 1.9.2-2 ยท EPL-1.0
- ubuntu noble: aspectj 1.9.5-2 ยท EPL-1.0
- ubuntu questing: aspectj 1.9.6-1
- ubuntu resolute: aspectj 1.9.6-1build1 ยท EPL-1.0
- ubuntu stonking: aspectj 1.9.6-1build1 ยท EPL-1.0
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms