Community
Participate
Working Groups
AspectJ 1.0 and 1.1 are behaving differently with respect to the qualifying type in a method call PCD. See the test case tests/bugs/CallReference.java AspectJ 1.1 is not picking out join points when a subtype of the defining type is used. I assume 1.0 is correct (but see [1]) because it tracks the programming guide (and the JLS). Because this might involve questions about what's correct, I'll include (my understanding of) the definition here in case the fix is to correct my interpretation or the programming guide. The programming guide says, ---- At a method call join point, the signature is a method signature whose qualifying type is the static type used to access the method. ---- So given class Super { void run() {} } class Sub extends Super { } class SubSub extends Sub { } Super is the declaring and defining type for run(). For the call new SubSub().run() SubSub is the qualifying type because the reference type qualifies the call. (i.e., because method dispatch occurs at runtime, with a search up the hierarchy if a method is not implemented directly in the class of the object. i.e., the guide intends to follow the definition of qualifying type for methods used in JLS 13.1.) Further, I understood from Erik that AspectJ accounts for polymorphism by having the pointcut match if one specifies a supertype of the signature type, so long as the method was defined in the specified supertype (or one of its supertypes). So to pick out all calls to that method, one should use the declaring type (in this case, Super); to restrict the calls matched, use a subtype. Indeed, for this reason, the locution target(Sub) && call(void run()) evolved to address the situation where the method was being invoked through a supertype reference, e.g., ((Super) new SubSub()).run() which would only be picked out by call(void Super.run()) and not by call(void SubSub.run()) even when the method was implemented in SubSub. This is the behavior of AspectJ 1.0. By contrast, AspectJ 1.1, given call(void Sub.run()) fails to pick out the invocations new Sub().run() new SubSub().run() though it would pick out new Sub().run() if the method were also defined in Sub, and not just in Super. Side notes: [1] In AspectJ 1.0, if I print the signature of the join point, it emits the defining type of the method as the type, and does not change depending on the static type used to access the method. That would seem to be a 1.0 (and 1.1?) limitation of the JoinPoint signature. [2] This should not be related to the case where older compilers use the declaring type of the method as the qualifying type, since this bug occurs when all sources are presented to ajc. I.e., the programming guide already incorporates the Java 1.0-1.1 change described in "Compilation of Symbolic References": http://java.sun.com/docs/books/jls/clarify.html http://java.sun.com/docs/books/jls/public-symref-compilation-rules.html
Adding keyword "info" since, if true, this is a limitation of our implementation of the language. Raising priority to P2 mainly to get confirmation before the next release whether the bug is valid or reflects my misinterpretation.
This is a manifestation of your issue [2] below, and you can probably fix it by compiling with -target 1.4. You should use javap to look at the bytecode generated by different compilers to see when the signature of the call is Super.run and when it is Sub.run. You're right in that we could fix this in the case where all of the sources are presented to ajc. We could do this in one of two ways: 1. Modify the compiler to always generate the "correct" declaring type even when not in 1.4 mode. I suspect that this would have unexpected consequences in older JVMs that were not expecting this -- which is why it is only enabled in 1.4 mode. 2. Modify the compiler to add some attributes to the .class file indicating the "correct" signatures for these method calls. This would require substantial work and isn't possible before 1.2. If we do this, it could be part of a general approach to passing information from the compiler to the weaver, such as the source line for method declarations, or the end bytecode for an exception handler. As I stated in mail to users, I consider any call PCD that uses a declaring type which isn't the top-most type for that signature to be potentially very confusing to the programmer and something that should be discouraged except for very specialized cases.
Since we switched the default mode of the compiler to -1.4, this is only an issue for people who compile with -1.3. We're never going to go back and do a large amount of work to fix this situation for the 1.3 mode, so I'm resolving the bug now.