Community
Participate
Working Groups
Code and exception below. Same result for HEAD and AspectJ 1.5.0.20051206103951 via AJDT. ------------------------------- bugs/CachedToString.java package bugs; import java.lang.ref.SoftReference; import junit.framework.TestCase; public class CachedToString { /** * @param args */ public static void main(String[] args) { new CacheGetterTest().testToString(); } public static class CacheGetterTest extends TestCase { static boolean runAdvice; public void testToString() { RandomToString me = new RandomToString (); runAdvice = false; String one = me.toString(); String two = me.toString(); assertFalse(one.equals(two)); runAdvice = true; one = me.toString(); two = me.toString(); assertTrue(one.equals(two)); } static class RandomToString { static aspect CacheToString extends CachedItem<String> { public pointcut context() : if(runAdvice); public pointcut caching() : execution(String RandomToString.toString()); } Random random = new Random(-1); public String toString() { return "" + random.nextFloat(); } } } public abstract static aspect CachedItem<Result> pertarget(results()){ SoftReference<Result> cache; boolean nullCache; // CODE writing pointcut trifecta separate context if extended and errors // getcode declaring-pointcuts-to-extend-with-caching START /** * Define join points to cache. * Must override, with staticly-determinable pointcuts * that pick out join points that are permitted. */ protected abstract pointcut caching(); /** ok to use Result field-get or return value */ private pointcut permitted() : get(Result *) || execution(Result *()) || call(Result *()) || call(Result.new(..)); /** Subaspects may add dynamic tests for the join points. */ pointcut context() : !disabled(); private pointcut disabled(); // fyi, undefined == none // getcode results START /** the pointcut composed from the user, as permitted, with context */ pointcut results() : caching() && permitted() && context(); // getcode results END Result around() : results() { // ... } // getcode declaring-pointcuts-to-extend-with-caching END Result result; if (nullCache) { result = null; } else if ((null == cache) || (null == (result = cache.get()))){ result = proceed(); if (null == result) { nullCache = true; } else { cache = new SoftReference(result); } } return result; } } } ------------------------------- exception C:\home\ws\main-31\my-ajbugs\aspectj-src\bugs\CachedToString.java [error] Internal compiler error java.lang.StringIndexOutOfBoundsException: String index out of range: -2 at java.lang.String.substring(String.java:1768) at org.aspectj.weaver.TypeFactory.createTypeFromSignature(TypeFactory.java:86) at org.aspectj.weaver.UnresolvedType.forSignature(UnresolvedType.java:426) at org.aspectj.weaver.UnresolvedType.getOutermostType(UnresolvedType.java:601) at org.aspectj.weaver.ResolvedType.isVisible(ResolvedType.java:1259) at org.aspectj.weaver.ResolvedType.addPointcutsResolvingConflicts(ResolvedType.java:1743) at org.aspectj.weaver.ResolvedType.getExposedPointcuts(ResolvedType.java:1716) at org.aspectj.weaver.ResolvedType.getExposedPointcuts(ResolvedType.java:1710) at org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceType.checkPointcutDeclarations(EclipseSourceType.java:293) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:414) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:419) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:419) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:419) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.completeTypeBindings(AjLookupEnvironment.java:231) at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.beginToCompile(Compiler.java:301) at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:315) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:811) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:230) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:156) at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112) at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60) at org.aspectj.tools.ajc.Main.run(Main.java:326) at org.aspectj.tools.ajc.Main.runMain(Main.java:240) at org.aspectj.tools.ajc.Main.main(Main.java:83) (no source information available) ABORT Exception thrown from AspectJ DEVELOPMENT This might be logged as a bug already -- find current bugs at http://bugs.eclipse.org/bugs/buglist.cgi?product=AspectJ&component=Compiler Bugs for exceptions thrown have titles File:line from the top stack, e.g., "SomeFile.java:243" If you don't find the exception below in a bug, please add a new bug at http://bugs.eclipse.org/bugs/enter_bug.cgi?product=AspectJ To make the bug a priority, please include a test program that can reproduce this exception. String index out of range: -2 when resolving pointcut declarations CachedToString when completing type bindings when batch building with classpath: c:\home\apps\jdk15\jre\lib\ext\dnsns.jar;c:\home\apps\jdk15\jre\lib\ext\localedata.jar;c:\home\apps\jdk15\jre\lib\ext\sunjce_provider.jar;c:\home\apps\jdk15\jre\lib\ext\sunpkcs11.jar;C:\home\ws\main-31\lib\junit\junit.jar;C:\home\wes\dev\tools\aspectj-1.5\lib\aspectjrt.jar; String index out of range: -2 java.lang.StringIndexOutOfBoundsException: String index out of range: -2 at java.lang.String.substring(String.java:1768) at org.aspectj.weaver.TypeFactory.createTypeFromSignature(TypeFactory.java:86) at org.aspectj.weaver.UnresolvedType.forSignature(UnresolvedType.java:426) at org.aspectj.weaver.UnresolvedType.getOutermostType(UnresolvedType.java:601) at org.aspectj.weaver.ResolvedType.isVisible(ResolvedType.java:1259) at org.aspectj.weaver.ResolvedType.addPointcutsResolvingConflicts(ResolvedType.java:1743) at org.aspectj.weaver.ResolvedType.getExposedPointcuts(ResolvedType.java:1716) at org.aspectj.weaver.ResolvedType.getExposedPointcuts(ResolvedType.java:1710) at org.aspectj.ajdt.internal.compiler.lookup.EclipseSourceType.checkPointcutDeclarations(EclipseSourceType.java:293) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:414) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:419) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:419) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.resolvePointcutDeclarations(AjLookupEnvironment.java:419) at org.aspectj.ajdt.internal.compiler.lookup.AjLookupEnvironment.completeTypeBindings(AjLookupEnvironment.java:231) at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.beginToCompile(Compiler.java:301) at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:315) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:811) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.doBuild(AjBuildManager.java:230) at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:156) at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:112) at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60) at org.aspectj.tools.ajc.Main.run(Main.java:326) at org.aspectj.tools.ajc.Main.runMain(Main.java:240) at org.aspectj.tools.ajc.Main.main(Main.java:83) 1 fail|abort, 1 error Signal 127
Created attachment 31284 [details] testcase patch Apply this patch to the tests project. This patch contains a simplified testcase which recreates the problem. In order for the problem to manifest it needs: 1. An inner generic aspect which contains more than one pointcut and some advice which uses all the pointcuts 2. An inner aspect which extends the generic aspect
When there are two pointcuts UnresolvedType.getOuterMostType() is called on a ReferenceType with signature "LPR119543$A" and also with signature "PPR119543$A<Ljava/lang/String;>;". Since there is a "$", this method returns UnresolvedType.forSigntaure(sig.substring(0,sig.indexOf("$") + ";") which in the second case is UnresolvedType.forSignature("PPR119543"). Since "PPR119543" starts with a "P" this calls TypeFactory.createTypeFromSignature("PPR119543"). Inside this method since we start with a "P" we assume this is parameterized and consequently look for the positions of "<" and ">" which in this case don't exist. The call signature.substring(1,startOfParams) becomes "PPR119543".substring(1,-1) which blows up with the StringOutOfBoundsException. In the case where there is only one pointcut we never call UnresolvedType.getOuterMostType() on a ReferenceType with signature "PPR119543$A<Ljava/lang/String;>;". Instead, it's only called on a ReferenceType with signature "LPR119543$A".
In the case when there are two pointcuts, the method ResolvedType.addPointcutsResolvingConflicts(List acc,List added, boolean isOverriding) is called with the parameterrs: acc = [] added = [pointcut PR119543$A<java.lang.String>.caching(), pointcut PR119543$A<java.lang.String>.permitted()] isOverriding = true This method iterates over the "added" list checking to see if there are any conflicts. At the end of every iteration it adds the pointcut to the acc list so it can calcualate possible conflicts with the other pointcuts it hasn't looked at yet. If there's only one pointcut then there clearly aren't any conflicts. If there are two pointcuts, then it just places the first one in the "acc" list since it hasn't discovered any conflicts yet. When it comes to look at the permitted() pointcut the caching() pointcut is in the acc list so it gets hold of this and starts comparing it for conflicts. The first check is whether they are the same. They're not so we continue. The second check is a call to isVisible(existing.getModifiers(), existing.getDeclaringType().resolve(getWorld()),this) where existing.getDeclaringType().resolve(getWorld()) is the ResolvedType with signature "PPR119543$A<Ljava/lang/String;>;" and this is the ResolvedType also with signature "PPR119543$A<Ljava/lang/String;>;". It is the call getOutermostType() on these ResolvedType's which cause the StringOutOfBoundsException.
Created attachment 31298 [details] improved testcase patch Apply this patch to the tests project. This testcase replaces the previously attached one as it checks for the advice not applied anywhere warning.
Created attachment 31299 [details] patch containing fix Apply to the weaver project. The fix is to use the erasureSignature rather than the signature when getting the outermost type. The erasureSignature doesn't know about "P"'s and "<"'s and works with the raw type.
fixes checked in.
fix available