[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Are aspects examining the running of Threads "special" in some way for AspectJ?


OK I located the line of code that was causing the slowness and the change is dramatic however, it's not clear why the programming error (on my part) resulted in the program going so slowly and this is probably the most interesting part of this question.

The problem was just a null pointer exception I elicited with this line:

System.out.println("Thread Group? " + nextThread.getThreadGroup().getName());

When the "nextThread variable referred to a Thread which was no longer alive (alive==false) , then that above line threw a NullPointerException because a "dead" thread has the property of belonging to no ThreadGroup.

nextThread.getThreadGroup returns null and I then attempt to call getName upon null .

A check for aliveness before executing the above line solves all problems.

But why? Why did an uncaught exception not blow the program stack but instead cause it to, it seems, do a really just a ton of processing resulting in the observed behaviour? Is this an AspectJ thing or something else I wonder. The program didn't die, it continued to execute and eventually (we're talking 45 minutes later) appeared on screen.

This is in contrast to the 15 seconds it takes to appear on screen after my error was fixed.


On 4/27/2012 7:56 PM, Andy Clement wrote:

A few things that I can initially think of:

- use jps/jstack to get the thread stacks of the JVM that you think is
hanging/going slow, is there an usual thread stack in there?

- you don't have any synchronization in your aspect for accessing the
collections.  I feel like I've had problems in the past when modifying
a collection I'm iterating over.  To tell if it is the body of your
advice that is behaving badly, just comment it all out (use empty
advice) - that will tell you if the weaving is introducing the issue
or the logic in the advice body is introducing the issue.

- The everything aspect looks ok.  I might do execution(public *
*(..)) just to reduce the output a bit, but it should be OK as you
have it.  You'd only get into issues here if you have types with loads
of methods, but then any problems would manifest as a weaving issue
(with the woven class getting too big for the JVM to handle).
Obviously instrumenting every little thing is going to have some
degree of performance impact.


On 27 April 2012 16:07, trhouse<trhouse@xxxxxxxxx> wrote:
Hi all,

I am just trying to use AspectJ to get a handle on all the threads that an
application runs. To start with, I just want to know how many there in how
many ThreadGroups.

I am using Loadtime Weaving to advise an admittedly large code base- a
popular open source IDE. Yes, it's huge.

What I am experiencing is the application "hangs" on start up without
terminating and without seeming to progress or so it seems. By "hangs" all I
mean is the application's splashscreen appears but the progress bar gets
stuck after a while and doesn't move. For half an hour, at which time I quit
the program.

It DOES work as intended - it does give me the information I am seeking, but
there just comes  a point when the output from this aspect is intermittent
and the progress bar is not moving and I can't prove it's not in long many
statement  infinite loop.

So my question is, is there something special about advising Runnable.run() that is doomed to slow everything to a crawl or get caught in an infinite loop for some reason?

The problem may be just  the sheer number of things I am trying to advise,
because the code base is so large. The only reason I don't think that   is
using another aspect, I can advise all methods and the application
successfully loads (then tells me I am out of memory and becomes uselessly
slow). The "everything" aspect is just

       pointcut captureAllMethods() : execution( * *(..));

and then I print out the signature and source location in the before() statement of the aspect.

I am sure you've all seen 1000 times before, but I included this aspect
along with the thread aspect at the bottom of this question.

Using this "everything" aspect also takes a long time but it does result ,
after many minutes, in the application being launched.

Oddly, when I apply BOTH aspects, the application I do get continuous output
from the "everything" aspect. which means it's still running.

In a slightly different version of the thread aspect, I make sure to !within
the aspect itself, just in case I was entering an infinite loop with the
aspect advising itself - something I don't see as even being possible given
the particular aspect.

I also do some System.out. printlns just to be sure that the thing is still
alive, which it is.

So I guess my other question is- have you been here before with really big
code bases? Is this just something that's bound to be unusable and the fact
that my  ( 64 bit AMD quadcore 8 gig RAM) computer runs for 45 minutes with
no sign of further progress is not a surprise to anyone?

Or is something else at work here?

Any advise is appreciated.

"Everything " aspect:
package recipePackage;

public aspect CaptureCallTargetRecipe

       pointcut captureAllMethods() : execution( * *(..))&&

// Advice declaration before() : captureAllMethods() {

             "Signature: "
                + thisJoinPoint.getStaticPart( ).getSignature( ));
             "Source Line: "
                + thisJoinPoint.getStaticPart( ).getSourceLocation( ));


--------------------------------------------------------------------------------------------------- "Thread" aspect: --------------------------------------------------------------------------------------------------- package recipePackage;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public aspect CaptureAllUniqueThreadsStartingRecipe
    static List<Thread>  threads = new ArrayList<Thread>(20);
    static List<ThreadGroup>  threadGroups = new ArrayList<ThreadGroup>(20);
    pointcut captureAllThreads(): execution(public void Runnable.run() ) ;

// Advice declaration before(): captureAllThreads() { Thread thisThread = Thread.currentThread(); if (thisThread == lastThread) { return; }

lastThread = thisThread;

                for (Iterator<Thread>  threadIterator = threads.iterator();
threadIterator.hasNext(); )
                    Thread nextThread = threadIterator.next();
                    if (thisThread == nextThread)
                        threadFound = true;


                for (Iterator<ThreadGroup>  threadGroupIterator =
threadGroups.iterator(); threadGroupIterator.hasNext(); )
                    ThreadGroup threadGroup = threadGroupIterator.next();
                    if (Thread.currentThread().getThreadGroup() ==
                        threadGroupFound = true;

System.out.println("------------------- THREAD DISCOVERED--------------------"); System.out.println("New thread discovered: " + thisThread); System.out.println("Thread List"); System.out.println("number Of Threads Created so far= " + threads.size()); System.out.println("number Of ThreadGroups Created far+ " + threadGroups.size()); System.out.println("Threads so far: ");

                int i=0;
                for (Iterator<Thread>  iterator = threads.iterator();
iterator.hasNext(); )
                    Thread nextThread = iterator.next();

                    System.out.println("Thread Name : " +
                    System.out.println("Alive? " + nextThread.isAlive());
                    System.out.println("Daemon? " + nextThread.isDaemon());
                    System.out.println("Thread Group? " +

System.out.println("------------------------------------------------------------"); }

    public volatile boolean threadFound;
    public volatile boolean threadGroupFound;
    public Thread lastThread;
    public Thread newThread;

aspectj-users mailing list
aspectj-users mailing list