Bug 389678 - OverWeaving: cannot compile ("key not found in wovenClassFile")
Summary: OverWeaving: cannot compile ("key not found in wovenClassFile")
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: 1.7.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 1.9.3   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-09-16 12:28 EDT by Alexander Kriegisch CLA
Modified: 2019-01-21 13:22 EST (History)
2 users (show)

See Also:


Attachments
Sample with 3 Eclipse projects (5.52 KB, application/x-zip-compressed)
2014-11-28 06:13 EST, Alexander Kriegisch CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Kriegisch CLA 2012-09-16 12:28:32 EDT
This happens in both 1.7.0 and 1.7.1.

I have three projects:
  - OverWeave_1: AJ project with class Application and aspect MyAspect
  - OverWeave_2: AJ project with aspect MyAspect2
  - Overweave_3: AJ project without any classes of its own, but OverWeave_1 on
    inpath and OverWeave_2 on aspectpath

OverWeave_3 runs fine with normal reweaving, applying both MyAspect{1,2} to Application. As soon as I enable project-specific AJ compiler settings in Eclipse (v4.2) and add "-Xset:overWeaving=true" to non-standard compiler options, I get this error on recompile:

java.lang.RuntimeException
at org.aspectj.weaver.WeaverStateInfo.findEndOfKey(WeaverStateInfo.java:408)
at org.aspectj.weaver.WeaverStateInfo.replaceKeyWithDiff(WeaverStateInfo.java:364)
at org.aspectj.weaver.bcel.LazyClassGen.getJavaClassBytesIncludingReweavable(LazyClassGen.java:707)
at org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor(BcelWeaver.java:1442)
at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1404)
 ... dJob.java:43)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

Compile error: RuntimeException thrown: key not found in wovenClassFile

I get compile errors when I try in via command line from the shell, too.
Comment 1 Andrew Clement CLA 2012-09-17 14:06:17 EDT
I don't think I've seen overweaving used in AJDT, it is primarily for loadtime weaving.  But, it should work (in theory).  Obviously the only real class (besides the aspects) that it will be affecting is Application.  I'll need to create some projects that mirror this configuration to try it out.  Were you just exploring this option or do you really need to use it with compile-time/binary weaving for some reason?
Comment 2 Alexander Kriegisch CLA 2012-09-17 15:23:15 EDT
Actually I just tried it in order to answer a related question on StackOverflow, because I got curious after having read your corresponding blog post. I expected to see MyAspect2 intercept some joinpoints generated by MyAspect, but did not get it to compile.

I remember I also tried with LTW, but needed to use a -Dsomething... or so there AFAIR. I saw that over-weaving was active with verbose weaver output logged to the console,mbut the effect was the same as reweaving, i.e. still no additionally matched joinpoints for exceution(* *(..)). Did you extend over-weaving to filter out those aspect-related joinpoints?

Cannot really try it live extensively now because I am on the road with iPad and only remote desktop access to my dev machine in the home office...
Comment 3 Alexander Kriegisch CLA 2012-09-30 03:28:13 EDT
Is there anything you need from me at this point to be able to continue? If so, please let me know.
Comment 4 Andrew Clement CLA 2012-10-01 11:06:48 EDT
Nope, nothing I need from your, I just need to find time to recreate.  

I wouldn't recommend this as a way to attempt to advise joinpoints introduced by an earlier aspect, if that is what you want to achieve.  That isn't a guaranteed behavior, it is currently a side effect of the limited implementation.  I imagine the ones you will see will be 'call' ones, I don't think you'd see 'execution' ones.
Comment 5 Tuomas Kiviaho CLA 2014-11-28 03:40:17 EST
I commented to bug 352389 about my similar problem with identical stacktrace as above but encountered it without using AJDT. I think that the fix to that bug introduced this bug as a side effect.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=352389#c2

I've patched successfully org.visit.aop.LazyClassGen with the following lines. (use bug marker to pinpoint the exact location)

// 352389: don't add another one (there will already be one there and this new one won't deserialize correctly)
if (myType != null && myType.getWeaverState() != null) { 
  if (world.isOverWeaving()) {
    Attribute attribute =myGen.getAttribute(WeaverState.AttributeName);
    myGen.removeAttribute(attribute);
  }
  myGen.addAttribute(Utility.bcelAttribute(new AjAttribute.WeaverState(
    myType.getWeaverState()), getConstantPool()));
}

It ensures coherence between adding of the key and finding it again.
Comment 6 Alexander Kriegisch CLA 2014-11-28 06:13:26 EST
Created attachment 248995 [details]
Sample with 3 Eclipse projects

OMG, back then I was on the road and totally forgot to add code to this (now old) ticket in order to make the problem rweproduceable. Here it is, just as explained in the bug description. I quickly retried with ApectJ 1.8.0 (part of my AJDT in Kepler), and the error is the same. I do not expect any other behaviour in 1.8.4.
Comment 7 Tuomas Kiviaho CLA 2019-01-17 04:44:19 EST
This is still happening with 1.9.2 (and previously with 1.8.6 as well). The same patch (as seen in earlier post) that I've used previously still applied.
Comment 8 Andrew Clement CLA 2019-01-18 20:32:46 EST
Ok, I've taken a deeper look here. Seems some folks are using overweaving, so let's make it behave a little better!

Building on the testcases that were attached (thanks!) - I've got those working but also looked at cases were we do further overweaving on top of those.  The rule is that once a type is overwoven you must only use overweaving on it after that (you cannot go back to 'regular weaving' mode).  I don't want to adjust the binary form of the WeaverState attribute because that can cause cross version compatibility problems, so I'm attaching some adding some meaning to a few characteristics of a WeaverState to tell me if a type ever gets overwoven.

We don't revert the change I made elsewhere to avoid creating two weaver state objects, instead we work with the one we have and we mark it when overweaving occurs. When overweaving occurs we switch off reweavable diff mode in the info attribute and set the 'previous version of the class' to a zero byte array. With reweavable diff mode off we no longer insert the key that need repairing. Since we don't insert it, it will deserialize OK in later weaves and when we do that, the zero byte 'original form of this class' tells us that this was previously overwoven.

With that information we can repeatedly overweave a type and get a nice error if we overweave then revert to regular.

note to self: can't turn off reweavable fully in the info attribute because that is also the flag that triggers whether we remember what aspects were previously woven into the target. We use that data for regular weaving (to verify they are around when repeating the weave) and in overweaving (to avoid re-applying them again).
Comment 9 Andrew Clement CLA 2019-01-21 13:22:47 EST
Fixes committed.