Hi Matthew,
1. I agree with you that there are two
distinct join point static part instances.
2. However, I do not believe they should be
equals either. I think it’s valuable to be able to track the two join
point static parts separately say in a hash map to record the distinct timings for
the distinct join points. Moreover it would be nice if you could serialize and
deserialize the static parts and have thisJoinPointStaticPart in one execution
be equals to the deserialized value that was stored in a previous one. That’s
how I’d like equals to work and a use case that I see as valuable.
3. I agree you can’t advise one of
them without advising the other but nonetheless they are distinct join point
static parts, and I don’t see them as equal. I don’t think that two
join points that will always match the same advice should be viewed as equal. E.g.,
it’s still useful to know that one of them takes say 99% of the time and
the other 1% even if you don’t have the source location information to
distinguish them. Again consider a profiling scenario: it’s useful to know
that of the six calls in this method one took 75% so you can investigate further.
I agree that you can’t rely having on source location (even line number) but
we should provide as much information as possible (e.g., by adding an attribute
when compiling sources with ajc) and the equals model ought to be consistent
with how it would behave if you did. It would be very unfortunate if the
semantics of equals varied depending on what level of debug information was
included, and worse if the solution were to ignore source location altogether
in considering equals. If static parts had an equals method like this then it
will require use of identity maps to distinguish them when dealing with call
join points. In my view that would be unfortunate.
Let me ask it another way, is there a use
case where having these two static parts be considered equals is valuable?
One other thought, what is a reasonable
way of handling a persistent map from static parts to data, so that you can update
information about the static part across runs? If the exact same program runs,
hopefully you could use hash codes for the static parts. But if the program
changes, what kind of changes would (and should) give rise to new hash codes?
From:
aspectj-users-bounces@xxxxxxxxxxx [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Matthew Webster
Sent: Friday, October 20, 2006
2:23 AM
To: aspectj-users@xxxxxxxxxxx
Subject: RE: [aspectj-users]
Custom JoinPoints
Ron,
There
are several points here:
1.
You are right about hashcode (I got things the wrong way round) but if I remove
that remark from my statement the first sentence is correct:
In
your example below the two invocations of go() are separate join points so have
their own JoinPoint.StaticPart instance. If they are written on separate lines
it becomes more obvious because their source locations will be different.
2.
The third sentence is a problem. The signatures are _not_ equal eventhough I
think they should be: they look the same and they are matched by the same very
specific pointcut. I suspect we need to add some "equals()" methods
to the runtime classes.
The
signatures for the 2 join points should be "equal()". If you invoked
"go()" in a loop then you would get the same StaticJoinPoint
instance.
3. The JoinPoint.StaticPart objects are not equal and shouldn't be. However
this distinction is below the level of granularity in the AspectJ join point
model _not_ a weakness in the weaving strategy, i.e. I cannot advise one
without advising both, and so cannot be relied upon: it is an artifact of the
runtime implementation. More importantly you cannot rely on source location: an
aspect should behave the same regardless of how it was woven and line numbers
can be omitted from the byte-code ("javac -o") so it's not just the
column that can be missing.
Matthew
Webster
AOSD Project
Java Technology Centre, MP146
IBM Hursley
Park, Winchester, SO21 2JN,
England
Telephone: +44 196 2816139 (external) 246139 (internal)
Email: Matthew Webster/UK/IBM @ IBMGB, matthew_webster@xxxxxxxxxx
http://w3.hursley.ibm.com/~websterm/[1]
"Ron Bodkin" <rbodkin@xxxxxxxxxxxxxx>
Sent
by: aspectj-users-bounces@xxxxxxxxxxx
19/10/2006 16:52
Please
respond to
aspectj-users@xxxxxxxxxxx
|
|
To
|
<aspectj-users@xxxxxxxxxxx>
|
cc
|
|
Subject
|
RE: [aspectj-users] Custom JoinPoints
|
|
Hi Matthew,
If the two static parts are considered equal in the sense
that sp1.equals(sp2) then they must have equal hash codes “If two objects
are equal according to the equals(Object) method, then calling the hashCode
method on each of the two objects must produce the same integer result.”
See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#hashCode() (breaking this contract causes lots of problems, e.g., in
using the java.util collections).
However, I think they shouldn’t be equal either.
Consider this case:
void workMethod() {
doWork(); for (int i=0; i<9999; i++) doWork();
}
I would like to distinguish the two join point static parts
and they shouldn’t equal in this respect (even though if they’re on
the same line we can’t distinguish which is which, which I think is more
of a limitation of the bytecode weaving strategy when we have source, that we
don’t implement SourceLocation.getColumn())
From:
aspectj-users-bounces@xxxxxxxxxxx [mailto:aspectj-users-bounces@xxxxxxxxxxx] On Behalf Of Matthew Webster
Sent: Thursday, October 19, 2006 3:32 AM
To: wes@xxxxxxxxxxxxxx; aspectj-users@xxxxxxxxxxx
Subject: RE: [aspectj-users] Custom JoinPoints
Wes,
In your example below the two invocations of go() are separate join points so
have their own JoinPoint.StaticPart instance. If they are written on separate
lines it becomes more obvious because their source locations will be different.
The signatures for the 2 join points should be "equal()" although
their hashcodes will not be the same (but could be if we used String.intern()).
If you invoked "go()" in a loop then you would get the same
StaticJoinPoint instance.
package ajsandbox;
public class JPSP {
static void go() {}
public static void main(String[] args) {
go();
go();
}
static aspect A {
before() : call(void JPSP.go()) {
System.out.println(thisJoinPointStaticPart.hashCode());
}
}
}
>The solution is to permit the aspect programmer to say "I
>won't be using the join point instance any more" by setting
>the (currently local-final) variable to null; in theory, if
>that's the only use, then the context data associated with
>the join point is eligible for garbage collection.
Unfortunately this won't work because the JoinPoint instance is passed as a
argument to the advice method so is on the stack and so cannot be collected.
Setting a local variable to null will have no effect. You will have the same
problem if you use the this(), target() or args() pointcuts.
>Currently the same join point instance is shared by multiple advice
>in different aspects.
Correct, but this would have to change and any aspect associated with a custom
JoinPoint factory would get its own custom instances. How else would you
support multiple custom factories?
>So it should be the case, e.g., that a
>change made by around advice to replace an argument is visible to
>less precedent advice.
Don't confuse a JointPoint instance with what it refers to i.e.
this/target/args. You may have 2 separate JoinPoint instances, possibly created
by different factories both referring to the same context.
Matthew Webster
AOSD Project
Java Technology Centre, MP146
IBM Hursley
Park, Winchester, SO21 2JN,
England
Telephone: +44 196 2816139 (external) 246139 (internal)
Email: Matthew Webster/UK/IBM @ IBMGB, matthew_webster@xxxxxxxxxx
http://w3.hursley.ibm.com/~websterm/[1]_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users