Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] Creation of parameterized ReferenceType not thread safe

Hi,

I am currently struggling with an IndexOutOfBoundsException deep in aspectj.

        at java.util.ArrayList.add(ArrayList.java:352)
        at org.aspectj.weaver.ReferenceType.addDependentType(ReferenceType.java:115)
        at org.aspectj.weaver.ReferenceType.<init>(ReferenceType.java:95)
        at org.aspectj.weaver.TypeFactory.createParameterizedType(TypeFactory.java:43)

After taking a deeper look into the code, I found out that the usage of TypeFactory.createParameterizedType() and in particular the instantiation of ReferenceType (line 43 of TypeFactory) is not thread safe. In a short program (see below) I could reproduce this issue, when passing the same instance of ResolvedType.

Is this a bug, or should this not happen when aspectj is used in a proper way?

Regards

Thorsten


--- sample program start ---
import java.util.concurrent.CountDownLatch;

import org.aspectj.weaver.ReferenceType;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.TypeFactory;
import org.aspectj.weaver.World;
import org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate;
import org.aspectj.weaver.reflect.ReflectionWorld;

public class Aspectj {

    public static void main(String[] args) {
        new Aspectj();
    }

    static World inAWorld = new ReflectionWorld(Aspectj.class.getClassLoader());

    static ReferenceType aBaseType;
    static {
        aBaseType = new ReferenceType("test", inAWorld);
        Java15ReflectionBasedReferenceTypeDelegate delegate = new Java15ReflectionBasedReferenceTypeDelegate();
        delegate.initialize(aBaseType, String.class, Aspectj.class.getClassLoader(), inAWorld);
        aBaseType.setDelegate(delegate);
    }

    public Aspectj() {
        int N = 25;
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(N);

        for (int i = 0; i < N; ++i)
            new Thread(new Worker(startSignal, doneSignal)).start();

        startSignal.countDown();
        try {
            doneSignal.await();
        } catch  (InterruptedException e){
            e.printStackTrace();
        }
    }

    class Worker implements Runnable {
        private final CountDownLatch startSignal;
        private final CountDownLatch doneSignal;

        Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
        }

        public void run() {
            try {
                startSignal.await();
                doWork();
                doneSignal.countDown();
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }

        void doWork() {
            for (int i = 0; i < 10; i++) {
                // using TypeFactory
                TypeFactory.createParameterizedType(aBaseType, new ResolvedType[0], inAWorld);

                // or creating ReferenceTypes directly
                //new ReferenceType(aBaseType, new ResolvedType[0], inAWorld);
            }
        }
    }

}
--- sample program end ---


Back to the top