|
I suggest that the problem is not the fact that the TagScript caches the Tag implementation, but the fact that the Tag implementation caches the heavy object after execution.
This is fortunate, because it's a whole lot easier for a Tag to stop caching it's state than it is for a TagScript to stop caching it's Tag implementation. It has to do with the way that caching works, which could be changed but not without big impact. See
Having looked at this some more, this TagScript should not clear its cache after run().
The cache reuses a Tag implementation between several runs of the same script, in the same thread. It does not reuse the same Tag implementation multiple times within the same script. The cache is a ThreadLocal object that is a member variable of TagScript. A seperate TagScript object is always created for every instance of a tag encountered in an XML document. So, there is no choice but to have a Tag implementation for every XML element in the document. What the cache does do is ensure that the second time you run the script in the same thread, it will not create a second set of Tag implementations. With a TagScript instance created by XMLParser in
its startElement and with every instance of TagScript declaring a ThreadLocal, jelly is unusable in tipical servlet environment. Caching should be at higher level. Jelly core should allow the run of scripts without leaving any trace of itself at the end. The attached pair of scripts seems to constantly raise the exception "Attempt to use a script that has been garbage collected.".
It combines a defined tag and an included script, quite a common situation, e.g. for Maven. I could not find a way to reproduce the bug with only one of the two ingredients. Invoke it with "java -jar target/fatJelly.jar blop.jelly". this is a problem with code introduced in the patch for
I think this is the right issue to post three possible approaches towards the tag-caching problem which was solved incompletely by the weak-reference wrapper (see Just to summarize the requirement: jelly scripts are structured using Script objects. Script functionality is provided by Tags and there is a need to reference tags from scripts and this maybe several times. The three approaches that I see are as follows: I think that, if we want to reach the release soon, we'd probably be better for 2. In cases 1 and 2, clean-up has to be made explicit (in case 3, gc-ing the context should be enough). So the lack of change in the API-signatures results in a change in the API documentation: users-scripts will need to add another call to clean-up. Thanks to bring your opinions ! paul I have now committed modifications to TagScript and JellyContext to prevent any caching outside of the JellyContext.
At least disposing of the JellyContext, the script objects, or calling the context.clear() will clear all references to tags. Jelly now builds fine. thanks paul Paul, I made some changes to your code based on my experience using Jelly. And I fixed the part about thread guarantees for Tag instances. But, it's basically unchanged, I hope you approve.
Hans, looks ok to me.
Will run some tests tonight Is "thread guarantees" the following excerpt of Tag interface javadoc?
> A Tag is only ever used by a single thread so that Tag developers Wouldn't i be simpler to say that Thread safety is guaranteed by the usage of a single context per thread ? Or do you have situations where a single context is used by several threads ? My tests and personal usages are fine with the current status of the tags, even with your memory-leak-test. paul Absolutely, this would be much easier. But it gets complicated when you look at what creating a new context means. Like, contexts search up the ie parent tree for variables and other stuff. And tags can search up from a thread tag to fiind parent...
Mmmh, that means that any operation that intend to use the script-to-tag association have to be run within the same thread. Maybe this could be more explicit somewhere.
Now... this means that JellySwing scripts should directly run in the AWT thread if they intend to run any jelly within the AWT thread (e.g. the body of Action), right? I've tried this and have managed to actually find back my tags and achieve a preliminary "reloadable" Swing components (so that a panel gets "re-populated" by jelly:swing as the result of an action). paul Well... It's not how Jelly works now, so I'll have to think about it. I'm really in favor of this: splitting off the different bits of functionality from JellyContext. While we're doing this, we could think about which parts are thread safe and which parts need to be kept in the same thread.
This bug report is now redundant and should be closed, right Hans and Paul?
Indeed.
We can clearly now say that this is fixed. paul |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
I'm backing it out until a replacement patch can be made that doesn't do this.