CVS: plexus-container-new/src/aspect/org/apache/plexus ComponentLeakAspect.java,NONE,1.1
[email protected] Sun, 25 May 2003 15:57:01 -0500
| Newsgroups | gmane.comp.java.plexus.devel |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/plexus/plexus-container-new/src/aspect/org/apache/plexus
In directory eng.werken.com:/tmp/cvs-serv2742/src/aspect/org/apache/plexus
Added Files:
ComponentLeakAspect.java
Log Message:
Adding an aspect that can be used to track down "component leaks". When
I built poolserver, I didn't realize that Summit was actually using some
components without ever releasing them. As a result, after a week, I
saw memory usage going through the roof.
Based on that experience, coupled with my desire to learn some AspectJ,
I thought this would be an ideal opportunity. To use the aspect:
- Build a plexus jar as follows: maven aspectj:compile jar:install
- Add the aspectj dependency to your project.xml file
- Run your project
Here is the type of output you will receive if you have no component
leaks (demo with a simple plexus command line application):
kaz@coco:~/work/src/simple/target$ java -jar simple-1.0-uber.jar
Hello World!
>> Non-Released Component Count: 0
On the other hand, if you have a leak, you will see the following:
kaz@coco:~/work/src/simple/target$ java -jar simple-1.0-uber.jar
Hello World!
>> Non-Released Component Count: 1
>>>> org.apache.plexus.examples.simple.DefaultHelloWorld@34a1fc
--- NEW FILE: ComponentLeakAspect.java ---
package org.apache.plexus;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import org.apache.plexus.service.repository.ComponentRepository;
/**
* Aspect to identify "component leaks". A component leak occurs when
* a component is looked up, but never released.
*
* @author <a href="[email protected]">Pete Kazmier</a>
* @version $Id: ComponentLeakAspect.java,v 1.1 2003/05/25 20:56:58 kaz Exp $
*/
aspect ComponentLeakAspect
{
private List components = new LinkedList();
/**
* This pointcut identifies the moment in time when we should
* actually print out the results we've been tracking in this
* aspect.
*/
pointcut repositoryDisposal():
call(void ComponentRepository.dispose());
/**
* The lookup pointcut has one subtly, we need to be carefull to
* remember that lookup(role, id), simply calls lookup(role). As
* a result, we need to make sure we exclude any calls to lookup()
* made from other calls of lookup.
*/
pointcut lookup():
call(Object ComponentRepository.lookup(..)) &&
!cflow(execution(Object ComponentRepository.lookup(..)));
/**
* The release pointcut is straightforward. We just need to keep
* track of the argument so we can remove it from our list.
*/
pointcut release(Object o):
call(void ComponentRepository.release(Object)) && args(o);
/**
* The around advice is used to get a reference to the returned
* object so we can add this to our list of components.
*/
Object around(): lookup()
{
Object result = proceed();
components.add(result);
return result;
}
/**
* The after advice here simply removes the component from our
* list.
*/
after(Object o): release(o)
{
components.remove(o);
}
/**
* We should print the results _before_ the component repository
* disposes() because part of the component repository's disposal
* includes the disposal of all components (and we can't be sure
* that it doesn't call release() which would affect our count,
* although after looking at the code, it really doesn't so it
* wouldn't matter, but that is an implementation detail that we
* should not know about. The other alternative would be to
* exclude the control flow of ComponentRepository.dispose() from
* our release pointcut).
*/
before(): repositoryDisposal()
{
System.err.println(">> Non-Released Component Count: " + components.size());
for (Iterator i = components.iterator(); i.hasNext(); )
{
System.err.println(">>>> " + i.next());
}
}
}