Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re[4]: [aspectj-users] Once again aboutn non-this access

Hello Ron,

Monday, February 2, 2004, 3:42:08 AM, you wrote:

RB> Hi Konstantin,

RB> I'd like to step back to look at your requirements. I gather
RB> you are trying to implement lazy loading, i.e, to detect object
RB> instances that haven't been loaded so you can load them on demand.
RB> Is that right?

Yes, you are right: object will be loaded on demand.

RB> If so, then you need a mechanism that checks field accesses
RB> (and accesses to a member of a collection!) to see whether these
RB> objects are loaded or not. In general, this has to be a dynamic
RB> test (with the exception of types that are loaded by value such as
RB> primitives). Consider:

RB> public class Tree {
RB>     private Tree parent;
RB>     private Collection children;
RB> ...
RB> }

RB> The persistence implementation should allow parent or any
RB> member of children to be lazily loaded. But both parent and the
RB> members of children are instances of Tree. So you really need a
RB> dynamic check for these accesses: the referred to instance might
RB> not be loaded, even though parent is a field on Tree and Tree is
RB> loaded. There are several approaches to implementing this kind of
RB> test (either proxies or dynamic tests), but describing the various
RB> options and how AspectJ can support them is too much detail for
RB> this email.


Certainly dynamic check is always needed to check whether object is
loaded or not. There is only one case when I do not need to perform
this checking - and actually it is most commonly used case: access to
self instance variables. Because in any case object is already
loaded.

RB> So I don't see how your original request will solve this
RB> problem.

Ok, I will try to briefly explain how lazy object loading was
implemented for my GOODS database (using my own bytecode preprocessor)
and for Perst using JAssist. First of all some introduction:

1. Each persistent object has object identifier (OID) - integer number
allowing to uniquely identify object within storage.
2. When object is loaded, it is obvious how to assign values to
scalar and string components of the object. But there are two possible
ways of representing references to other persistent objects.
Since Java is safe language with static type checking,
reference field can refer only to the object which type is the same or
derived from the type of the field.
- So we can store OID of referenced
  object somewhere also and store null in reference field (in this case
  we trap access to the field and load it on demand).
- Or we can create stub object which type is the same as real type of
  referenced object which which fields are not loaded yet.

Both approaches has their advantages and disadvantages.
I prefer second approach.
3. Persistent object has load() method which checks if object is
already loaded and id not - loads its fields (I want to remember that
we use second case)


Now how to implement transparent persistency with this model:
1. At the beginning of each instance method we insert load() method.
So it will ensure that object is loaded.
If access to the fields of "foreign" (non-this) objects is not
allowed (it is assumed that setter/getter methods are used instead),
then this is all we need. We should not insert any extra code or do
extra checks - fields of this object can be always accessed without
any extra overhead.
2. If access to foreign object fields is allowed, then before
each such access we should invoke load() method for target object.
3. To be able to detect modified objects, before each assignment to the field
modify() method should be called (it is also possible to call it after
update).

Unfortunately (as I already told), it is not possible to implement
this scenario with AspectJ - it doesn't allow to distinguish this and
non-this access. Alternative solution is to be able tot detect access
to reference fields (so we insert load method for each access to
reference field). Number of invoked load() method with this approach
is the same as with my approach. But size of code is larger - because
in my apporach load() is inserted only in one place - in method body,
and in this approach - in each access to the method or field.
Also in this case check for null should be done before invocation of
laod() method.

But I also do not know how to implement this approach with AspectJ.
It requires definition of pointcut like this:

getField(): get(!transient !static Persistent+ *.*);

(it means access to all fields referencing persistent objects).
But such pointcut is not accepted by AspectJ.


All other approaches requires insertion of AspectJ code before (or
after) each field access. Since OO program used to access fields very
frequently (there are even recommendations to avoid use of local
variables because them makes refactoring more difficult), size of the
program is significantly increased after such preprocessing and speed
- significantly decreased. I think that AOP should be not just a toy
or facility for debugging and adding trace messages to your application,
but really powerful system, which can provide performance compatible (or
even better) than alternative solutions. In case of persistence or
remoting aspects alternative solution is to load object explicitly.
That is why I think that such optimization is absolutely needed.



RB> But implementing the request does raise some interesting
RB> points in their own right. So I'll also address the topics of
RB> optimization, a pointcut that expresses the test that you said you
RB> wanted, and how this might be enabled by future versions of the
RB> AspectJ language.

RB> 1. I would like to see more optimization of the this and
RB> target pointcut descriptors. There are several cases where the
RB> emitted bytecode performs runtime checks that can be proven to be
RB> true or false in all cases. 

RB> I'd like to see is an optimization of this(Type) (or
RB> this(var) where var is of Type), which the compiler can always
RB> resolve to be true or false at compile-time. This results in code
RB> that may or may not be optimized away by the VM (JIT). I'd most
RB> like to see this optimization to improve the accuracy of the tools
RB> support (which currently identifies too many places as advised). I
RB> believe AspectJ 1.0.x did have this optimization.

RB> There are several possible optimizations in emitted bytecode
RB> that it would be desirable for the AspectJ compiler to implement.
RB> But I think the team's current emphasis on making the compiler
RB> reliable, scalable, and fast is the right priority.

RB> 2. I personally don't think adding special case logic to say
RB> "access to a foreign field" is common enough to warrant a special
RB> case language extension, and as I will explain below, what you
RB> really want can't be expressed without a language extension.

>>From your clarification, you wanted to identify about access to
>>fields from a different TYPE and not from a different instance.
>>Translating into AspectJ (plus a logical quantification):

RB> for all types T:
RB> for any supertype S of T:
RB>   pointcut externalGet(T t) : 
RB>       this(t) && get(* *.*) && !get(* S.*);

RB> If AspectJ had my proposed type pattern for a type or its supertypes (-), this
RB> would reduce to:
RB> for all types T:
RB>   pointcut externalGet(T t) : 
RB>       this(t) && get(* *.*) && !get(* T-.*);

RB> An alternative version (that would also work for static fields) is:
RB> for all types T:
RB>   pointcut externalGet() : 
RB>       // access to a field from any jp within type T or a parent type...
RB>       (within(T-) || 
RB>       // or from any ITD's defined on T or a parent type
RB>        withincode(* T-.*(..)) || withincode(* T-.new(..))) && 
RB>       get(* *.*) && !get(* T-.*);

RB> For implementing object persistence, you probably don't care about static fields...

RB> It _is_ feasible to write a special case of this pointcut for
RB> a single type in AspectJ (just plug in the appropriate value of T
RB> and expand to include T and ALL its supertypes). 

RB> But AspectJ doesn't currently offer a way to quantify over
RB> types like this at compile-time. Unfortunately, I don't believe
RB> even the proposed pertype aspect would help here. 

RB> I am hoping that when AspectJ supports generics, it will be
RB> possible to express this kind of pointcut, e.g.,
RB>   pointcut <T> externalGet(T t) : 
RB>       this(t) && get(* *.*) && !get(* T-.*);
RB>   after <T> (T t) returning: externalGet(t) {
RB>       t.dirty = true;
RB>   }

RB> I believe that advice for this pointcut could still be
RB> implemented as a method through type erasure (i.e., it wouldn't
RB> require macro expansion), though I don't have a fully developed
RB> proposal for how AspectJ should handle generics. (as an aside 

RB> So hopefully AspectJ will grow into solving your stated design by 
RB> 1) defining generics support that will capture it
RB> 2) adopting my proposal for using T- for a type and all its supertypes
RB> 3) possibly optimizing the code for this() tests. But note
RB> that if we have #1 and #2, optimizing this isn't even necessary
RB> (using the within version of the pointcut will be optimized!)

RB> Although I don't see how detecting foreign field access helps
RB> with persistence or remote object invocation.

RB> Ron

RB> Ron Bodkin
RB> Chief Technology Officer
RB> New Aspects of Software
RB> m: (415) 509-2895

>> ------------Original Message------------
>> From: Konstantin Knizhnik <knizhnik@xxxxxxxxx>
>> To: Wes Isberg <aspectj-users@xxxxxxxxxxx>
>> Date: Sat, Jan-31-2004 10:20 AM
>> Subject: Re[2]: [aspectj-users] Once again aboutn non-this access
>> 
>> Hello Wes,
>> 
>> 
>> Thank you very much for your response.
>> 
>> WI> You can use within(), but it doesn't really help.
>> 
>> WI> A join point has a signature specifying only types, so
>> WI> it seems like a dynamic test is needed.
>> 
>> With dynamic check such feature has completely no sense.
>> The only reason of this my request is optimization of preprocessed
>> code. In good OO programs instance variables are usually accessed only
>> by self or derived classes. Access to foreign variables is not
>> recommended (better to use setter/getter methods). In Smalltalk such
>> access is not even possible! Now lets see what's happen if I want to
>> implement persistence or remoting aspect. The main idea is
>> transparently load target object. As far as Java is not
>> Smalltalk nobody can prevent programmer from accessing instance
>> variable of other objects. So I insert before access to the field
>> code performing loading of the object. But for self instance variable
>> this code is absolutely useless - self object is already loaded.
>> And as far as access to self instance variable happens most frequently
>> (in well designed program as I said it is 100%), been not able to
>> distinguish self and not-self access cause significant performance and
>> byte code size overhead. Concerning your example, I already mentioned
>> in my previous mail that exact check (that != this) is not
>> needed: I just want to avoid generation of extra code for normally
>> accessed instance variables. It will cause completely no problems if value
>> of target reference is equal to this.
>> 
>> Still wonder why nobody else request this feature before - size of
>> code and will be significantly decreased and performance - increased
>> (not extra method call for each field access). I think that is very
>> important for production applications based on AspectJ.
>> 
>> WI> Assuming the join point signature were changed to include
>> WI> an attribute for the invoking reference indicating
>> WI> whether it was directly (but explicitly or implicitly)
>> WI> via "this", consider
>> 
>> WI>     class Foo {
>> WI>         int i;
>> WI>         Bar o;
>> WI>         int incBoth(Foo foo) {
>> WI>            return (i++ + foo.i++); // foo:foo==this?
>> WI>         }
>> WI>         int incMe() {
>> WI>            return incBoth(this);
>> WI>         }
>> WI>         int incMeAgain() {
>> WI>            Foo me  = this;        // not a join point
>> WI>            return incBoth(me);
>> WI>         }
>> WI>         public String toString() {
>> WI>            Bar p = (o == null ? Bar.CONST : o);
>> WI>            return p.toString();
>> WI>         }
>> WI>     }
>> 
>> WI> If it were supported, it would seem arbitary and
>> WI> would hide the real semantics, which are dynamic.
>> WI> So to me it looks impractical and more confusing than
>> WI> helpful.
>> 
>> WI> Wes
>> 
>> WI> P.S. - As for whether this is the right place or whether
>> WI> anyone replies to a message, that is all purely consensual.
>> WI> No one is obliged to answer anyone's email.  There is
>> WI> a general obligation on the part of the committers to
>> WI> participate in discussions on aspectj-dev pertaining to
>> WI> the *development* of the technology, but aspectj-users is
>> WI> for users to communicate with each other.  If people
>> WI> require immediate support when writing AspectJ code,
>> WI> they can solicit professional support here or on
>> WI> aspectj-dev.  (It's generally considered improper for
>> WI> those offering support services to solicit people who
>> WI> post to mailing lists unless the posters explicitly
>> WI> request professional support.)  Also, emails on
>> WI> questions that can't be resolved by considering the
>> WI> documentation tend to spark more interest, as do emails
>> WI> from posters who in the past have contributed correct
>> WI> and well- written questions and answers.
>> 
>> WI> Konstantin Knizhnik wrote:
>> 
>> >> Hello,
>> >> 
>> >> Three days ago I have sent the question to this mailing list about
>> >> possibility to distinguish access to this and foreign
>> >> objects with AspectJ pointcuts. I received no replies to my message.
>> >> I wonder if this mailing list is the right place for asking such
>> >> questions? Its it really checked by Aspect-J developers?
>> >> 
>> >> I briefly repeat my message here. To be able to efficiently implement
>> >> persistence and remoting aspects, it will be very useful to be able to
>> >> distinguish access to self instance fields and access to fields of
>> >> other objects (non-this access). In last case, such accesses should be
>> >> wrapped with advice code which is responsible for object loading.
>> >> But there is completely no need to insert such code for access to self
>> >> instance variables. Right now I find only one way how to express
>> >> correspondent pointcut in AspectJ: comparing result of this() and
>> >> target(). But it is translated by AspectJ in runtime check! So it is
>> >> in any case impossible to avoid AOP overhead for accessing self
>> >> instance fields.
>> >> 
>> >> Actually what I want to know
>> >> 1. Is such feature currently supported by Aspect-J?
>> >> 2. If not - what is the reason:
>> >> - nobody requested such feature before
>> >> - technical problems with implementing this feature (it seems to me
>> >> that there are completely no problems)
>> >> - some ideological arguments against adding this feature
>> >> - this feature will not be used by most of Aspect-J users
>> >> - performance is not critical for most of Aspect-J users.
>> >> 3. Also are there plans to implement it in 1.2 version of Aspect-J?
>> >> 
>> 
>> WI> _______________________________________________
>> WI> aspectj-users mailing list
>> WI> aspectj-users@xxxxxxxxxxx
>> WI> http://dev.eclipse.org/mailman/listinfo/aspectj-users
>> 
>> 
>> 
>> -- 
>> Best regards,
>>  Konstantin                            mailto:knizhnik@xxxxxxxxx
>> 
>> _______________________________________________
>> aspectj-users mailing list
>> aspectj-users@xxxxxxxxxxx
>> http://dev.eclipse.org/mailman/listinfo/aspectj-users
>> 
>> 
RB> _______________________________________________
RB> aspectj-users mailing list
RB> aspectj-users@xxxxxxxxxxx
RB> http://dev.eclipse.org/mailman/listinfo/aspectj-users



-- 
Best regards,
 Konstantin                            mailto:knizhnik@xxxxxxxxx



Back to the top