Community
Participate
Working Groups
Although initial smoke tests with OTDT and AJDT in the same Eclipse install went fine, it has been reported that this combination could throw exceptions, leaving the system in a broken state. E.g.: java.lang.ClassFormatError: Duplicate field name&signature in class file org/eclipse/jdt/core/JavaCore We should investigate if OT/Equinox and AspectJ's JDT Weaving interact in any bad ways.
Created attachment 202012 [details] console output of eclipse console output when starting eclipse with the following installation details: AspectJ/XRef/Eclipse Weaving Service Feature 2.1.3.e37x-2011-628-1900 Eclipse SDK 3.7.0.I20110613-1736 Equinox Weaving SDK 1.0.100.HEAD Object Teams Development Tooling 2.0.0.201106131847 Object Teams Equinox Integration 2.0.0.201106070730 Scala IDE fir Eclipse 2.0.0.beta09-29-201107201639
Don't let this one fall through the cracks.
Created attachment 202710 [details] ajdt console messages OK, installing the above tool versions except for Scale IDE passed the smoke test, I only see lots of warnings from the AJDT on the console. I don't know if these are "normal" messages. FWIW, this installation was made in the following order: 1. Eclipse SDK 3.7.0 2. OTDT 2.0.0 (from indigo repository) 3. AJDT from their update site. As a quick test I installed the shipped OTSample-Flightbonus, which runs OK, but during this process the following exception was logged: eclipse.buildId=I20110613-1736 java.version=1.6.0_22 java.vendor=Sun Microsystems Inc. BootLoader constants: OS=linux, ARCH=x86, WS=gtk, NL=en_US Command-line arguments: -os linux -ws gtk -arch x86 -data /home/stephan/workspaces/ot-ajdt-testing Error Sat Sep 03 21:45:09 CEST 2011 Problems occurred when invoking code from plug-in: "org.eclipse.debug.core". java.lang.IllegalArgumentException: Argument "clazz" must not be null! at org.eclipse.equinox.weaving.internal.caching.BundleCachingService.storeClass(Unknown Source) at org.eclipse.equinox.weaving.adaptors.WeavingAdaptor.storeClass(Unknown Source) at org.eclipse.equinox.weaving.hooks.WeavingHook.recordClassDefine(Unknown Source) at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:604) at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findClassImpl(ClasspathManager.java:567) at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClassImpl(ClasspathManager.java:490) at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass_LockClassName(ClasspathManager.java:469) at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(ClasspathManager.java:456) at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(DefaultClassLoader.java:216) at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:400) at org.eclipse.osgi.internal.loader.SingleSourcePackage.loadClass(SingleSourcePackage.java:35) at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:473) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:429) at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417) at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107) at java.lang.ClassLoader.loadClass(ClassLoader.java:266) at org.eclipse.jdt.internal.debug.ui.JavaDebugOptionsManager.activate(JavaDebugOptionsManager.java:673) at org.eclipse.jdt.internal.debug.ui.JavaDebugOptionsManager.launchChanged(JavaDebugOptionsManager.java:688) at org.eclipse.jdt.internal.debug.ui.JavaDebugOptionsManager.launchAdded(JavaDebugOptionsManager.java:682) at org.eclipse.debug.internal.core.LaunchManager$LaunchNotifier.run(LaunchManager.java:440) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) at org.eclipse.debug.internal.core.LaunchManager$LaunchNotifier.notify(LaunchManager.java:428) at org.eclipse.debug.internal.core.LaunchManager.fireUpdate(LaunchManager.java:990) at org.eclipse.debug.internal.core.LaunchManager.addLaunch(LaunchManager.java:688) at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:843) at org.eclipse.debug.internal.core.LaunchConfiguration.launch(LaunchConfiguration.java:703) at org.eclipse.debug.internal.ui.DebugUIPlugin.buildAndLaunch(DebugUIPlugin.java:928) at org.eclipse.debug.internal.ui.DebugUIPlugin$8.run(DebugUIPlugin.java:1132) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
After trying also the install order Eclipse->AJDT->OTDT I could only find one bug located in the OTDT (bug 356670). The exception from comment 2 happened again when building projects for the first time after workbench relaunch. This is clearly not in OTDT code. Still it could be some bad interaction between both weaving mechanisms. I also saw one more exception in AJDT code: java.lang.IncompatibleClassChangeError: Expecting non-static method org.eclipse.ajdt.core.javaelements.AspectJMemberElement.escapeMementoName(Ljava/lang/StringBuffer;Ljava/lang/String;)V at org.eclipse.ajdt.core.javaelements.AspectJMemberElement.getHandleMemento(AspectJMemberElement.java:107) The full stacktrace is a happy mix of JDT/OTDT/AJDT but starting from these frames: org.eclipse.ajdt.core.codeconversion.ITDAwareNameEnvironment.find(ITDAwareNameEnvironment.java:103) org.eclipse.jdt.internal.core.SearchableEnvironment.findType(SearchableEnvironment.java:294) everything is basically AJDT. OTOH, the attachment in comment 1 clearly indicates an error that occurred on the OTDT side. Are you able to reproduce that error without also installing the Scala IDE? Depending on which plugins cause the conflict I would try to get help from the respective other plugin authors.
OK, with also Scala IDE in the mix I can see this exception: java.lang.ClassFormatError: Duplicate interface name in class file org/eclipse/jdt/debug/core/IJavaStackFrame The OTDT indeed weaves into this interface. I'd have to figure out if Scala IDE is also interested in this type. After seeing this exception jdt.debug is not working. Building actually still works, but other actions fail, too. E.g., opening a team type throws: java.lang.NegativeArraySizeException at org.eclipse.jdt.internal.compiler.lookup.MethodBinding.getSourceParameters(MethodBinding.java:757) .... at org.eclipse.jdt.internal.compiler.Compiler.resolve(Compiler.java:1066) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process_aroundBody0(CompilationUnitProblemFinder.java:234) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process_aroundBody1$advice(CompilationUnitProblemFinder.java:244) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process_aroundBody2(CompilationUnitProblemFinder.java:1) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder$AjcClosure3.run(CompilationUnitProblemFinder.java:1) at scala.tools.eclipse.contribution.weaving.jdt.core.CompilationUnitProblemFinderAspect.ajc$around$scala_tools_eclipse_contribution_weaving_jdt_core_CompilationUnitProblemFinderAspect$1$3edd546aproceed(CompilationUnitProblemFinderAspect.aj:1) at scala.tools.eclipse.contribution.weaving.jdt.core.CompilationUnitProblemFinderAspect.ajc$around$scala_tools_eclipse_contribution_weaving_jdt_core_CompilationUnitProblemFinderAspect$1$3edd546a(CompilationUnitProblemFinderAspect.aj:49) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder._OT$process$orig(CompilationUnitProblemFinder.java:201) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder._OT$process$chain(CompilationUnitProblemFinder.java) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.AdaptorActivator._OT$CompilationUnitProblemFinder$activateChecker$base(AdaptorActivator.java) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.AdaptorActivator.access$5(AdaptorActivator.java:1) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.AdaptorActivator$__OT__CompilationUnitProblemFinder.activateChecker(AdaptorActivator.java:289) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.AdaptorActivator._OT$CompilationUnitProblemFinder$activateChecker$process(AdaptorActivator.java:275) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder._OT$process$chain(CompilationUnitProblemFinder.java) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java) at org.eclipse.jdt.internal.core.CompilationUnitProblemFinder.process(CompilationUnitProblemFinder.java:300) Here we see an interesting mix of weavings in action.
Summarizing my observations so far: I could NOT reproduce a complete failure as reported in comment 1. Can you provide steps how exactly you got into that state? Interplay between AJDT and OTDT has a few quirks but looks actually more or less usable. Please report if anything is really broken here. When adding Scala IDE to the mix things start to get crazy.
(In reply to comment #6) > I could NOT reproduce a complete failure as reported in comment 1. I spoke too soon: after relaunching Eclipse once more I can see things similar to the attachment of comment 1. Investigating. The failure does not require the Scala IDE in the mix.
I've tried followin: - installed OTDT - installed AJDT - wrote sample OT/J project, sample AJDT project, sample Java project Observations: - AJDT started reporting some errors () but I ignored them since everything seemed to work After one more restart I've got java.lang.ClassFormatError: Duplicate field name&signature in class file org/eclipse/jdt/internal/ui/packageview/PackageExplorerPart. Package explorer doesn't work anymore. I'm attaching workspace and log.
Created attachment 202715 [details] sample projects Sample projects
Created attachment 202716 [details] log file for workspace with sample projects
(In reply to comment #8) > Observations: > - AJDT started reporting some errors () but I ignored them since everything > seemed to work That corresponds to my first impression, too. > After one more restart I've got java.lang.ClassFormatError: Duplicate field > name&signature in class file > org/eclipse/jdt/internal/ui/packageview/PackageExplorerPart. > Package explorer doesn't work anymore. Yes, thanks for mentioning, here's the key to the problem: the restart. AJDT uses equinox weaving which caches woven class files on disk. At the next launch the woven, cached files will be retrieved and fed into the normal class loading routine. Effect: the OT runtime will weave the classes as normal, but they already have our changes in them. Thus the duplicate declarations in the resulting classes. There's a quick and ugly workaround: locate the cache directory inside the eclipse installation, on my system it is eclipse/configuration/org.eclipse.osgi/bundles/437/data the number 437 will probably vary but you will recognize the directory by - large total size, I currently see 27kB, all others are below 10kB. - it contains a subdirectory whose name is a 32 char hash string If you wipe that directory before each launch, the caching effect should be gone. For a real solution I will ask on equinox-dev what needs to be done to integrate the OT weaver with that caching mechanism, and secondly I could just add a mark to woven class files so that we can always avoid double weaving. In order to try out any improvements we would need a development build of the AJDT that is compatible with current milestones towards Eclipse 3.8. I couldn't find such. Does anyone know if they actually have builds compatible with 3.8Mx?
(In reply to comment #11) > There's a quick and ugly workaround: locate the cache directory inside > the eclipse installation, on my system it is > eclipse/configuration/org.eclipse.osgi/bundles/437/data > the number 437 will probably vary but you will recognize the directory by > - large total size, I currently see 27kB, all others are below 10kB. > - it contains a subdirectory whose name is a 32 char hash string > If you wipe that directory before each launch, the caching effect should > be gone. Comment from the AJDT team: invoking eclipse with -clean should also wipe the cache, so that should be an easier workaround :)
Hi, is there any progress on this issue? I would _really_ like to use OTDT in the same eclipse with AJDT and this is a major obstacle. Starting eclipse with -clean is not a realistic option. :-(
(In reply to comment #13) > Hi, is there any progress on this issue? > > > I would _really_ like to use OTDT in the same eclipse with AJDT and this is a > major obstacle. Starting eclipse with -clean is not a realistic option. :-( Good news: meanwhile I got the necessary help from the AJDT team for debugging the AJDT in a 3.8-based Eclipse. I will now start investigating individual conflicts.
(In reply to comment #4) > I also saw one more exception in AJDT code: > > java.lang.IncompatibleClassChangeError: Expecting non-static method > org.eclipse.ajdt.core.javaelements.AspectJMemberElement.escapeMementoName(Ljava/lang/StringBuffer;Ljava/lang/String;)V > at > org.eclipse.ajdt.core.javaelements.AspectJMemberElement.getHandleMemento(AspectJMemberElement.java:107) This was bug 357552 (fixed).
(In reply to comment #3) > java.lang.IllegalArgumentException: Argument "clazz" must not be null! > at > org.eclipse.equinox.weaving.internal.caching.BundleCachingService.storeClass(Unknown > Source) > at org.eclipse.equinox.weaving.adaptors.WeavingAdaptor.storeClass(Unknown > Source) > at org.eclipse.equinox.weaving.hooks.WeavingHook.recordClassDefine(Unknown > Source) > at > org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:604) I can observe this exception in the debugger and there seems to be another exception as the root cause which never is reported: java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782) at java.util.ArrayList$Itr.next(ArrayList.java:754) at org.aspectj.weaver.World$TypeMap.demote(World.java:1098) at org.aspectj.weaver.World$TypeMap.demote(World.java:1076) at org.aspectj.weaver.World.demote(World.java:1781) at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1796) at org.aspectj.weaver.bcel.BcelWeaver.weaveWithoutDump(BcelWeaver.java:1638) at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1401) at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1187) at org.aspectj.weaver.tools.WeavingAdaptor.getWovenBytes(WeavingAdaptor.java:468) at org.aspectj.weaver.tools.WeavingAdaptor.weaveClass(WeavingAdaptor.java:319) at org.eclipse.equinox.weaving.aspectj.loadtime.OSGiWeavingAdaptor.weaveClass(OSGiWeavingAdaptor.java:121) at org.eclipse.equinox.weaving.aspectj.AspectJWeavingService.preProcess(AspectJWeavingService.java:151) at org.eclipse.equinox.weaving.adaptors.WeavingAdaptor.weaveClass(WeavingAdaptor.java:245) at org.eclipse.equinox.weaving.hooks.WeavingHook.processClass(WeavingHook.java:126) at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.defineClass(ClasspathManager.java:597) This exception causes the following line to be skipped: result = classloader.defineClass(name, classbytes, classpathEntry, entry); which then triggers the IAE reported above. Is OT/Equinox triggering some concurrency for which the AJ weaver is not prepared?
> Is OT/Equinox triggering some concurrency for which the AJ weaver is not > prepared? Yes, the AspectJ weaver does not support multiple threads running in the same instance. 'Regular' loadtime weaving synchronizes on the classloader instance, this route doesn't appear to do that.
(In reply to comment #17) > > Is OT/Equinox triggering some concurrency for which the AJ weaver is not > > prepared? > > Yes, the AspectJ weaver does not support multiple threads running in the same > instance. 'Regular' loadtime weaving synchronizes on the classloader instance, > this route doesn't appear to do that. Thanks for letting me know. Unfortunately this could mean we have an real incompatibility here: OT/Equinox runs using osgi.classloader.lock=classname and AJDT seems to require osgi.classloader.lock=classloader (the latter being the default is nothing is specified). We need to avoid locking on the classloader, because the inherent two-way dependencies between aspects and the base classes into which dispatch code is woven can otherwise cause deadlocks during class loading: Thread A loads a base class which now contains calls into the aspect which forces loading of the aspect. Thread B loads the aspect which contains calls to the base class which forces loading of the base class. If A and B run in parallel deadlock may occur. Andy, do you have a different strategy for avoiding this kind of deadlock or does the situation just not occur (how?) in AspectJ? Using the classloader lock for OT/Equinox would hopefully avoid the exception but may potentially deadlock eclipse. Adding synchronization to the AspectJ weaver sounds like a big task. At a first look I see no easy solution for this exception.
AspectJ weaving doesn't trigger class load events. Weaving of base will simply occur by accessing the bytecode for the aspect (if it references it), it won't need to be loaded by the classloader. > Thread A loads a base class which now contains calls into the aspect which > forces loading of the aspect. > Thread B loads the aspect which contains calls to the base class which > forces loading of the base class. > If A and B run in parallel deadlock may occur. No, they simply queue (if grabbing a CL lock before weaving), whoever gets there first would weave what they wanted (base/aspect) then load/define it, then the other guy will get a chance to do his thing. Perhaps there are some situations I've not thought through, but I've never seen a deadlock.
Here is a deadlock problem in STS that is related to JDT Weaving. This is not coming from the AspectJ weaver, but from Equinox Weaving: https://issuetracker.springsource.com/browse/STS-1445 With the current way that Equinox Weaving is implemented, we can't 100% prevent a deadlock, but in most situations we can avoid it if we carefully pre-load some offending classes.
ah yes, that one. I guess it happens so infrequently, I forget them. We never did implement that preloading did we.
Sorry my first post was written in haste. I am just not finding I have much time to think about this issue given other stuff I'm working on. > Adding synchronization to the AspectJ weaver sounds like a big task. Yep.
Hi Andrew, (In reply to comment #20) > Here is a deadlock problem in STS that is related to JDT Weaving. This is not > coming from the AspectJ weaver, but from Equinox Weaving: > > https://issuetracker.springsource.com/browse/STS-1445 Thanks for the pointer! Yes, that's exactly the same issue that we were also seeing in OT/Equinox. Martin's comment from 11/Jan/11 mentions exactly those options that we are successfully using ever since we first came across this kind of deadlock. The comments also remind me that now that we have Java 7 I should actually try to do it the new way with osgi.classloader.type=parallel Here Java 7 acknowledges the fact that in environments like OSGi it is perfectly legal to have cycles among classloaders, thus locking the classloader is inherently prone to deadlocks. > With the current way that Equinox Weaving is implemented, we can't 100% prevent > a deadlock, but in most situations we can avoid it if we carefully pre-load > some offending classes. Pre-loading specific classes may solve one particular instance of the problem but doesn't make the technology safe per se. So, if the AspectJ weaver were thread-safe, I'd recommend you use the same VM options, but since it seems to be not thread-safe this is not an option, currently. OTOH, I could try to find a set of classes to pre-load in the OTDT so that we could try running with the class loader lock - fingers crossed. That set will be large, hm. I'm not promising that this will yield a solution.
The initial bug was caused by a conflict between the OT weaver and the caching service that comes with equinox.weaving (which is used by the AJDT). Initially, the OT weaver would re-weave already woven classes. I made experiments to let the OT weaver detect already woven classes, but this fails if only a few OT-woven classes are cached and others are freshly woven (due to globally unique IDs that are generated during weaving, which will be inconsistent when mixing cached and freshly woven classes). I also tried to trigger caching all OT-woven classes but apparently the caching service is not ready for caching classes from multiple weavers. I've filed bug 358290 for that issue. For the time being we have to disable caching, which can be done by several means: 1. remove cache files from the file system 2. reset caches using the big switch: "-clean" 3. disabling the caching service All seem to work, but 1. is plain ugly, 2. has unintended side effects, 3. looks most promising but requires to edit the following config file: eclipse/configuration/org.eclipse.equinox.simpleconfigurator/bundles.info Find the lines for org.eclipse.equinox.weaving.caching and org.eclipse.equinox.weaving.caching.j9. In both lines change the trailing true to false. I guess that's the best we can do at this point.
Status summary: - 2 dependent bugs fixed (bug 357552, bug 357557) - 1 minor bug open, but not strictly needed (bug 356670). - caching can only work after bug 358290 has been fixed, but a workaround exists. Remaining issue: concurrency of classloading in different threads. This issue can be worked around by removing the following line in config.ini: osgi.classloader.lock=classname There is some inherent risk of deadlock involved when removing this line, for which nobody seems to have a full answer. If deadlocks occur involving OT-code, or code that is woven by the OTDT, I can try to avoid each individual situation by pre-loading some classes. It's balancing the risk of a deadlock against the havoc caused by concurrency exceptions, which may just break individual functions of the IDE. At this point I don't see, what else I could do. Unfortunately, my fixes for bug 357552 and bug 357557 were too late for Indigo SR1. I understand that AJDT builds based on Eclipse 3.8 / 4.2 will not be published in the near future. So I'll do the following: After SR1 is released I will backport the patches and upload an intermediate version that will hopefully be compatible with the newest AJDT at that time.