天天看点

Important aspects in AspectJ

In this blog, I will show some important and basic aspects.

1) locking operations.

Given the locking operations such as

synchronized ("ss") {                    

                      sharedV =1;

                      sharedM =2;                      

                      sharedV =3;

                      sharedM =4;                    

                    }

I want to print the lock information before locking and unlocking.

So, I add the aspect:

    before(Object l): lock() && args(l) && scope() {

        System.out.println("lock:" + l.hashCode());

    }

    after(Object l): unlock() && args(l) && scope() {

        System.out.println("unlock:" + l.hashCode());

    }

lock() and unlock() matches the locking and unlocking operations, arg() catches the lock information.

These primitives conbine and define a pointcut.

the pointcut prefixed with before(...) or after(...) is an advice, meaning the moment just before (or after) the event defined by the pointcut.

For each advice, we define some actions. Such actions will be carried at the moment corresponding to the advice.

Make sure you provide the option "-Xjoinpoints:synchronizations" to aspecj compiler. By default, lock() and unlock() are not matched.

The trace is:

lock:3680

unlock:3680

//============================================

The second important events are about fieldget or fieldset:

    pointcut staticFieldGet(): get(static * *) && scope() ;

defines the events of getting static fields.

    before(): staticFieldGet()

    {

        String id = getId(thisJoinPointStaticPart); // field signature    

        Class owner = thisJoinPointStaticPart.getSignature().getDeclaringType();    // ownerclass type

        SourceLocation loc = location(thisJoinPointStaticPart); // which line does the field get happen

        System.out.println(loc);

    } 

It is an advice, defining the moment just before a fieldget event. Actions are carried at the moment.

The trace produced by the actions is:

idpublic static final java.io.PrintStream java.lang.System.out

class java.lang.System

Simple.java:18

As seen, the advice also matches java.io.PrintStream class!

! it cannot instrument the jdk classes because they are loaded before the weaver is started. Also, aspectj does not support re-transformation.

Here, the aspectj catches the calls of the jdk methods, but still, it catches inside an application code.

In other words, it only instrument the application code for identifying the jdk calls.

//===============================================

The third class is the initialization:

 public pointcut anyConstructorExecution() :

        execution(new(..)) &&scope();

matches the event of any object creation via the new instruction.

    before():anyConstructorExecution()

    {

        System.out.println("here:" + thisJoinPointStaticPart.getSignature());

    }

defines that some information should be printed at the moment just before the object creation.

A trace is:

here:Simple()

here:Simple.1()

here:Simple.2()

//=================================================

For completeness,  I also attach the most important aspects:

import org.aspectj.lang.JoinPoint.StaticPart;
import org.aspectj.lang.reflect.SourceLocation;

public aspect CommonAspects {
	//============range===============
	pointcut scope(): !within(CommonAspects) && !cflow(within(CommonAspects));
	public pointcut aroundAdviceSupported() : !handler(*)
	    && !initialization(new(..)) && !preinitialization(new(..)) &&scope();
    public pointcut withinAnyJavaCode() :
        within(java..*) || within(javax..*);

    public pointcut notWithinJavaCode() :
        !withinAnyJavaCode();
	//============range=================
	
	
	
	
	//============locking==============
	before(Object l): lock() && args(l) && scope() {
		System.out.println("lock:" + l.hashCode());
	}
	
	after(Object l): unlock() && args(l) && scope() {
		System.out.println("unlock:" + l.hashCode());
	}
	//============locking==============
	
	
	
	//=============field================
	// add maybeshared() in the pointcut to reduce matching.
	pointcut staticFieldGet(): get(static * *) && scope() ;
	pointcut staticFieldSet(Object value): set(static * *)&& args(value)&& scope() ;	
	pointcut fieldGet(Object owner): get(!static * *) && target(owner) && scope();  
    pointcut fieldSet(Object owner, Object value): set(!static * *) && target(owner)&&args(value) && scope() ;		
    before(): staticFieldGet() // already matches the jdk classes, such as: static final java.io.PrintStream java.lang.System.out
    {
    	String id = getId(thisJoinPointStaticPart); // field signature    
		Class owner = thisJoinPointStaticPart.getSignature().getDeclaringType();	// ownerclass type
		SourceLocation loc = location(thisJoinPointStaticPart); // which line does the field get happen
		System.out.println(loc);
    } 
    before(Object value): staticFieldSet(value)
    {
    	System.out.println("set the static field " + " as " + value);
    }   
    before(Object owner): fieldGet(owner)
    {
    	System.out.println("get field of " + owner);
    }
    before(Object owner, Object value): fieldSet(owner,value)
    {
    	System.out.println("set field of " + owner + " as " + value);
    }    
    private String getId(StaticPart sp) {
		return sp.getSignature().toLongString().intern();
	}
    private SourceLocation location(StaticPart sp){
	    return sp.getSourceLocation();
	}	
    public pointcut withinSetter() :  // require !static?
        withincode(void set*(*)); // use any return type? multiple parms?

    public pointcut withinGetter() : 
        withincode(!void get*()); // permit parms? require !static?

    
    //================field==============
    
    
    
    //================<init>==============
    public pointcut anyConstructorExecution() : 
        execution(new(..)) &&scope(); // execution means the range from the very beginning to the very ending.
    // initialization means the period from the return of the super to the return of the current constructor.
    // preinitialization means hte period from the start of the current constructor to the start of the suepr.
    public pointcut anyPublicConstructorExecution() : 
        execution(public new(..))  &&scope();
    public pointcut anyNonPrivateConstructorExecution() :
        execution(!private new(..)) &&scope();
   
    
    before():anyConstructorExecution()
    {
    	System.out.println("here:" + thisJoinPointStaticPart.getSignature());
    }
    //================<init>==============
    
    
    
	
	//=============method invocation=======
	public pointcut anyMethodExecution() : 
        execution(* *(..));

    public pointcut anyPublicMethodExecution() : 
        execution(public * *(..));

    public pointcut anyNonPrivateMethodExecution() : 
        execution(!private * *(..));

    before():anyMethodExecution()
    {
    	
    }    
	//=============method invocation=======
    
	
	
	
	//=============special method==================
	public pointcut anyRunnableImplementation() :
        staticinitialization(Runnable+);

    public pointcut anyGetSystemErrOut() :
        get(PrintStream System.err) || get(PrintStream System.out);

    public pointcut anySetSystemErrOut() :
        call(void System.setOut(..)) || call(void System.setErr(..));
    


    public pointcut toStringExecution() :
        execution(String toString()) && !within(String);

    /** call or execution of any Thread constructor, including subclasses */
    public pointcut anyThreadConstruction() :
        call(Thread+.new(..)) || execution(Thread+.new(..));

    /** 
     * Any calls to java.io classes 
     * (but not methods declared only on their subclasses).
     */
    public pointcut anyJavaIOCalls() :
        call(* java.io..*.*(..)) || call(java.io..*.new(..));

    /** 
     * Any calls to java.awt or javax.swing methods or constructors 
     * (but not methods declared only on their subclasses).
     */
    public pointcut anyJavaAWTOrSwingCalls() :
        call(* java.awt..*.*(..)) || call(java.awt..*.new(..))
        || call(* javax.swing..*.*(..)) || call(javax.swing..*.new(..));

    public pointcut cloneImplementationsInNonCloneable() :
        execution(Object !Cloneable+.clone());
        
    public pointcut runImplementationsInNonRunnable() :
        execution(void !Runnable+.run());
        
    /** any calls to java.lang.reflect or Class.get* (except getName()) */
    public pointcut anySystemReflectiveCalls() :
        call(* java.lang.reflect..*.*(..))
        || (!call(* Class.getName())
            && call(* Class.get*(..)));

    /** standard class-loading calls by Class and ClassLoader
     * Note that `Foo.class` in bytecode is `Class.forName("Foo")`,
     * so 'Foo.class' will also be picked out by this pointcut.
     */
    public pointcut anySystemClassLoadingCalls() :
        call(Class Class.forName(..))
        || call(Class ClassLoader.loadClass(..));

    public pointcut anySystemProcessSpawningCalls() :
        call(Process Runtime.exec(..))
        || call(Class ClassLoader.loadClass(..));

    /** Write methods on Collection
     * Warning: Does not pick out iterator(), even though
     * an Iterator can remove elements.
     */
    public pointcut anyCollectionWriteCalls() :
        call(boolean Collection+.add(Object)) 
        || call(boolean Collection+.addAll(Collection)) 
        || call(void Collection+.clear())
        || call(boolean Collection+.remove(Object))
        || call(boolean Collection+.removeAll(Collection))
        || call(boolean Collection+.retainAll(Collection));
        
    public pointcut mostThrowableReadCalls() :
        call(* Throwable+.get*(..))
        || call(* Throwable+.print*(..))
        || call(String Throwable+.toString(..));

    public pointcut exceptionWrappingCalls() :
        (args(Throwable+,..) || args(.., Throwable+))
        && (set(Throwable+ Throwable+.*)
            || (call(* Throwable+.*(..)) 
                || call(Throwable+.new(..))));

    public pointcut anyCodeThrowingException() :
        execution(* *(..) throws Exception+)
            || execution(new(..) throws Exception+);   
	//=============special method==================
	

}
           

继续阅读