Fix memory leak when used from multiple JRuby runtimes. #74
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
If json/ext/parser is required from multiple JRuby runtimes in the same JVM, it will leak memory for every runtime beyond the first.
Test script: https://gist.github.com/971319
The leak is caused by taking references to the runtimes in the RuntimeInfo class, particularly the WeakHashMap<Ruby, RuntimeInfo>. Note the caveat in the WeakHashMap JavaDocs:
Implementation note: The value objects in a WeakHashMap are held by ordinary strong references. Thus care should be taken to ensure that value objects do not strongly refer to their own keys, either directly or indirectly, since that will prevent the keys from being discarded. Note that a value object may refer indirectly to its key via the WeakHashMap itself; that is, a value object may strongly refer to some other key object whose associated value object, in turn, strongly refers to the key of the first value object. One way to deal with this is to wrap values themselves within WeakReferences before inserting, as in: m.put(key, new WeakReference(value)), and then unwrapping upon each get.
This applies here, because each RuntimeInfo has internal references to the corresponding Ruby object via the members jsonModule, stringExtendModule, etc -- these will all contain internal references to the runtime.
Using WeakReference as the value object instead fixes the leak as shown by the test script.
Note: also reported here. It looks like active development for all platforms is going on in this repository now, so I submitted the pull request here. Let me know if this is not the desired workflow.