Community
Participate
Working Groups
'declare parents' statements are not honored by -XnoWeave. Take this program: public class WhatAmI { public static void main(String[] args) { System.err.println("I'm a main method:"); WhatAmI instance = new WhatAmI(); // Should *not* be serializable if (instance instanceof java.io.Serializable) throw new RuntimeException("I should not be serializable"); } } aspect A { declare parents: WhatAmI implements java.io.Serializable; } ajc WhatAmI.java A.java -XnoWeave java WhatAmI returns: java.lang.RuntimeException: I should not be serializable at WhatAmI.main(WhatAmI.java:9) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) The problem is that the compilation stage applies the ITD and then generates code for it - meaning the weaver doesn't have to do it. (and so in the case of -noweave the weaver can't decide *not* to do it!). This is unlike other ITDs where although they are 'applied' at compile time to satisfy type checks, the code generator at compile time does not produce code for them - this means the weaver applies them again at weave time and so it can choose not to do it in the case of -noweave.
There are two situations to think about: declare parents: Blah extends SuperBlah declare parents: Blah implements IBlah In trying to fix the first case I get (at weave time): error can't use declare parents to change superclass of binary form 'WhatAmI' (implementation limitation) which might be reasonable but was a surprise I wasnt expecting ! This compiler limitation doesnt apply for 'declare parents: implements' though. However, if I can't fix it in both cases - should I fix it for just one? Is it better if we just put out a warning message if using -XnoWeave with "declare parents:" that says these features aren't compatible. The other reason I wanted to fix this was -Xreweavable. The list of aspects that modify a type is collected at weave time - on a subsequent weave we verify this list of aspects is around. In the case of using "declare parents:" reweavable doesn't record that an aspect affected a type because it was not done by the weaver. However, even if I did propagate this knowledge from compile time->weave time so it could be recorded in the reweavable state, it wouldn't be useful because when attempting the reweaving and reverting to the 'unwoven' form of the class file, it would have already had the "declare parents:" declarations applied. (Am I making sense here?).
Should I just put out an error/warning message when we see this combination of inputs (declare parents/XnoWeave) ... ?
declare parents interacts more strongly tightly with the compiler than any other construct in AspectJ. I think that for 1.2 you might have to just make it an xlint warning to use it with XnoWeave or Xreweavable. Not being able to use declare parents with interfaces and reweavable is a real bummer. Here's a sketch of what it would take to support declare parents properly in the weaver. 1. The main reason it wasn't done originally is error checking. There are a lot of checks to make sure that a class properly implements an interface or can extend a different class. These checks are already implemented for the eclipse compiler, but they need to be duplicated on ResolvedTypeX's to make sure that declare parents is being used correctly in the weaver. 2. After making this change, you'd need to modify the compiler to emit classfiles with unmodified superclass and interfaces. This could be tricky. The current implementation just adds interfaces and a new superclass to the eclipse SourceTypeBinding objects; however, it doesn't modify the underlying TypeDeclarations. You'd need a hook to modify the Classfile constructor to use the original interfaces and superclass from the SourceTypeBinding. This is doable, but I'm almost certain would require another patch to the jdt.core code.
I have done the first part of the solution which is to get the compiler to emit class files that don't have the modified hierarchies. This was relatively straightforward, I just record the original superclass and interface set before any declare parents are processed and when emitting the class file I use the recorded information. For declare parents 'implements' I think that is almost enough but declare parents extends is much more messy. I've so far found the following checks that need to be implemented if allowing extends at weave time: - if you inherit methods you cannot override them and reduce their visibility - if you inherit methods you cannot have incompatible return types (java1.5 will make this a little messier) - if you inherit abstract methods and you are not abstract you need to provide an implementation - if you inherit abstract methods and don't provide implementations you have to be abstract - if you override an instance method you cannot make your overridden version static - you cannot extend a final class - the Object class cannot be subject to declare parents extends I think that covers many cases - of course ITDs have to be taken into account. I've not looked at field inheritance yet. I've also uncovered a problem to do with declare parents: <SomeType>+ extends <SomeClass> If we process a subtype of <SomeType> before we process <SomeType> then you get an error (as SomeClass doesn't typically fit into the extends hierarchy). If we process <SomeType> first and it just extends from Object then we can usually put <SomeClass> in as its parent, then there is no problem when processing the subtype of <SomeType> because one of its parents already extends <SomeClass>. clear? :)
*** Bug 74061 has been marked as a duplicate of this bug. ***
Fix available: BUILD COMPLETE - build.427 Date of build: 01/07/2005 09:52:56 Time to build: 107 minutes 25 seconds Last changed: 01/07/2005 08:08:11 Latest good AspectJ jar available at: download.eclipse.org/technology/ajdt/dev/aspectj-DEVELOPMENT.jar Modifying super calls in the bytecode were the main bit of implementation - the rest of the work is checks to ensure you aren't violating the rules, as outlined in a previous comment in this bug report. The checks might not currently be perfect but they are good enough for a first release of the functionality.