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==================
	

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值