Conversation
JDK issues about the problem: * https://bugs.openjdk.java.net/browse/JDK-8136353
| var tag = ref.get | ||
| if (tag == null) { | ||
| cache.remove(runtimeClass1) | ||
| tag = cache.get(runtimeClass1).asInstanceOf[jWeakReference[ClassTag[T]]].get |
There was a problem hiding this comment.
in theory this .get could return null...
|
Would be interesting to write a test similar to the one in the JDK bug: but I would need some help since this is my first contribution 😂 |
|
Thanks for bringing up this issue. An alternative fix might be to limit our use of the cache to when We use I'll try out some variations of the fix and also try to replicate the leak in a test. |
|
Related fix for |
|
I made an error in the merge
|
|
... and I didn't spot it in the review |
|
@jtjeferreira Could you describe the classloader heirarchy that showed up the problem? Is |
|
I've pushed a commit to deal with the race condition of the weak reference immediately getting cleared. I do the same as we do in Baseline: This PR: With the cache disabled altogether: In this microbenchmark, the weak reference version has similar execution time to the uncached version. But it does reduce allocation rates. |
This is from a play 2.7.x project when running the application. Each time the application is stopped and started new classloaders are created. Luckily I have this diagram that I used to understand what was going on: Starting from the bottom:
The workaround I used in playframework/playframework#10500 is to move loading of |
|
I also found some interesting discussion here http://mail.openjdk.java.net/pipermail/mlvm-dev/2018-March/006847.html |
|
I was trying to get you a screenshot from the profiler (from running scripted tests of playframework/playframework#10500 without the fix ), but eclipse MAT does not report it, and my yourkit trial just expired (which AFAICT was the one that was showing it clearly) |
ba1aff6 to
c18fb61
Compare
|
/rebuild |
retronym
left a comment
There was a problem hiding this comment.
I wasn't able to reproduce with a test case. I've proceeded with my slight refactor of your original idea, together with a system property to disable the cache altogether.
| var tag = ref.get | ||
| if (tag == null) { | ||
| cache.remove(runtimeClass1) | ||
| tag = cache.computeTag(runtimeClass1).asInstanceOf[ClassTag[T]] |
There was a problem hiding this comment.
would it be benefitial to add the tag back into the cache here?
There was a problem hiding this comment.
This is a rare case so I don't think its worth it.
Thanks for the merge! Do you plan to port this to 2.13? |
|
Yeah, I will correct the merge error and take this all over to 2.13.x after 2.13.4 is released. |
fix ClassTag#cache leak
fix ClassTag#cache leak

I was diagnosing some classloader leaks and the profiler pointed to
ClassTag#cacheJDK issues about the problem:
Also this is not a problem in 2.13.x because the cache does not exist there. See gitter question https://gitter.im/scala/contributors?at=5f941163a0a3072b43a099b7