gragent Groovy Hotswap

Since upgrading to IDEA 14 EAP, I've tried to use DCEVM with Groovy. I've noticed that I can't make any changes that change the methods or number of closures in the file without it breaking, it gives me missing method errors for functions it would normally be calling elsewhere in the file, or telling me that the method has different signatures than it really does. Restarting the VM lets the program work, so I know that the code is valid. My thought is maybe gragent is not calling the swapInit method. The problem is that I didn't use this feature in IDEA 13 so I don't know if it's supposed to work, or if it's an EAP issue or not. And I have no way to confirm whether or not the agent is doing anything (or calling swapInit), I only know it's on the command line shown by IDEA and checked in debugger/HotSwap IDE settings. I can't (don't know how to) call swapInit directly to confirm that if the agent called it, that it would work, because I need to call it not just on the main class but also all of its closures, which I don't know how to enumerate.

Is there any way someone from Jetbrains can help me debug this or let me know if this is a limitation of the gragent, or if this is even supposed to work. As of now I can hotswap Java entirely (adding/removing/changing methods and classes), but for Groovy it only really works if I make simple modifications to existing methods.

I am using DCEVM 1.7.0_51 (full version) and IDEA IU-138.1696.2

1 comment
Comment actions Permalink

It's possible there is also callsite caching issues, but at least in the common case I see, the metaclasses are not getting updated. Let's say I have a method with a closure called in it like .find { X it -> it.something }. Now I add a call before that in the same method like .find { == "whatever" }. Now what happens is I get a "no signature for method MyClass$" and the "possible" solutions show doCall(X), which is actually from the original closure.

If I examine Class.forName("MyClass$_myMethod_closure2") and Class.forName("MyClass$_myMethod_closure3") in debugger, I see that closure3 has doCall matching the original closure taking X, and closure2 has doCall taking Object. This makes sense, since I added the new closure before the original, the original was renamed to closure3 and properly reloaded. But if I get the MetaClasses for the closure 2 and closure 3, they seem to represent the old state.


Please sign in to leave a comment.