Certain elements of AspectJ's semantics are difficult to implement without making modifications to the virtual machine. One way to deal with this problem would be to specify only the behavior that is easiest to implement. We have chosen a somewhat different approach, which is to specify an ideal language semantics, as well as a clearly defined way in which implementations are allowed to deviate from that semantics. This makes it possible to develop conforming AspectJ implementations today, while still making it clear what later, and presumably better, implementations should do tomorrow.
According to the AspectJ language semantics, the declaration
before(): get(int Point.x) { System.out.println("x =" + x); }
should advise all accesses of a field of type int and name x from instances of type (or subtype of) Point. It should do this regardless of whether all the source code performing the access was available at the time the aspect containing this advice was compiled, whether changes were made later, etc.
But AspectJ implementations are permitted to deviate from this in a well-defined way -- they are permitted to advise only accesses in code the implementation controls. Each implementation is free within certain bounds to provide its own definition of what it means to control code.
In the current AspectJ compiler, ajc, control of the code means having source code for an aspect and all the code it should advise available at compile time. This means that if some class Client contains code with the expression new Point().x (which results in a field get join point at runtime), the current AspectJ compiler will fail to advise that access unless Client.java is compiled at the same the aspect is compiled. It also means that join points associated with code in precompiled libraries (such as java.lang) are not advisable.
Aspects that are defined perthis or pertarget also have restrictions based on control of the code. In particular, at a join point where the source code for the currently executing object is not available, an aspect defined perthis of that join point will not be associated. So aspects defined perthis(Object) will not create aspect instances for every object, just those whose class the compiler controls. Similar restrictions apply to pertarget aspects.
Other AspectJ compilers, indeed, future versions of ajc, may define code the compiler controls more liberally.
Control of the code may mean that classes need only be available in classfile or jarfile format. So, even if Client.java and Point.java were precompiled, their join points would still be advisable. In such a system, though, it might still be the case that join points from code of system libraries such as java.lang would not be advisable.
Or control of the code could even include system libraries, thus allowing a call join point from java.util.Hashmap to java.lang.Object to be advised.
All AspectJ implementations are required to control the code of the files that the compiler compiles itself.
The important thing to remember is that core concepts of AspectJ, such as the join point, are unchanged, regardless of which implementation is used. During your development, you will have to be aware of the limitations of the ajc compiler you're using, but these limitations should not drive the design of your aspects.