javaspringaspectjspring-aopgigaspaces

AspectJ autoproxy fails with GigaSpaces 8 and Spring 3 because class is loaded by different classloader


We're using GigaSpaces version 8.0.0 (yes it's old) along with Spring 3 (yes it's also old). There are two modules A and B. A is the "main" module that reads and writes to the space and exposes some remote services. A and B run separately. B creates an instance of an entity that has a field that is a class object. This class only exists in B; A does not know about it. It then makes a remote call to A that ends up writing the instance to the space.

Later, A loads up this entity and creates an instance of the remote class by doing entity.getClassObject().newInstance(). This works even though this class doesn't exist in the A's runtime classloader, because the classloader for this class is the LRMI (light remote-method invocation) classloader that comes with GigaSpaces. I guess it knows how to instantiate it.

The problem arose when we added an aspect to A. We have existing code that autowires an instance of the remote class using A's application context and also initializes it using initializeBean. The autowiring and initialization worked fine until we added the aspect. Now, during initialization, it attempts to see if the advices in the aspect apply to the bean that is being initialized. As part of this process, it attempts to create an instance of the class using Class.forName and the bean's class' name. This results in a ClassNotFoundException because the class obviously does not exist in the runtime class loader. So AspectJ resolves the type as MissingResolvedTypeWithKnownSignature instead of failing immediately. But eventually there is a failure when AspectJ tries to find the superclass of the class because it doesn't have that information, and it throws the following exception:

org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type com.mypackage.MyRemoteClass
 [Xlint:cantFindType]
        at org.aspectj.weaver.reflect.ReflectionWorld$ExceptionBasedMessageHandler.handleMessage(ReflectionWorld.java:129)
        at org.aspectj.weaver.Lint$Kind.signal(Lint.java:328)
        at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.raiseCantFindType(MissingResolvedTypeWithKnownSignature.java:232)
        at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.getDeclaredInterfaces(MissingResolvedTypeWithKnownSignature.java:86)
        at org.aspectj.weaver.ResolvedType.getDirectSupertypes(ResolvedType.java:82)
        at org.aspectj.weaver.patterns.TypePattern.matchesSubtypes(TypePattern.java:178)
        at org.aspectj.weaver.patterns.ExactTypePattern.matchesSubtypes(ExactTypePattern.java:74)
        at org.aspectj.weaver.patterns.TypePattern.matchesStatically(TypePattern.java:130)
        at org.aspectj.weaver.patterns.KindedPointcut.fastMatch(KindedPointcut.java:141)
        at org.aspectj.weaver.internal.tools.PointcutExpressionImpl.couldMatchJoinPointsInType(PointcutExpressionImpl.java:84)
        at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:238)
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:200)
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:254)
        at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:286)
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87)
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:386)
...

Is there any way around this? I can think of two approaches, but I'm not exactly sure how to go about it. One is to somehow prevent Spring from checking to see if the aspect applies, and the other is perhaps to swap out the runtime classloader with one that delegates to the LRMI classloader if it can't find a class in the runtime class loader. But I'm not sure if I can even get an instance of the LRMI classloader.

Has anyone run into this sort of issue?


Solution

  • This is a known issue in the version of AspectJ that I was using (1.6.12). It appears to have been fixed in later versions -- at least since 1.8.14 (which is what I upgraded it to). So upgrading my version of AspectJ fixed this issue.