Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential ThreadLocalMap.Entry accumulation in JoinPointImpl #302

Closed
KimmingLau opened this issue Apr 2, 2024 · 5 comments · Fixed by #303
Closed

Potential ThreadLocalMap.Entry accumulation in JoinPointImpl #302

KimmingLau opened this issue Apr 2, 2024 · 5 comments · Fixed by #303
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@KimmingLau
Copy link
Contributor

KimmingLau commented Apr 2, 2024

Our application is trying to upgrade aspectjweaver from 1.9.5 to 1.9.21.2 recently. But after upgradtion we found that memory usage in the old generation grows faster and FGC became more frequently, by the way we use jdk 1.8 and CMS+ParNew.

So we had made a heapdump and then found that the size of ThreadLocalMap in our application thread was much larger than before. And I've figured out that the value of growing entry in ThreadLocalMap is from field org.aspectj.runtime.reflect.JoinPointImpl#arcIndex. That's why I tried to review change histroy in JoinPointImpl and issue the following comments 43df701#r140486566

Sorry for that I cannot provide more information about problem from which our application is suffering, such as monitor graph or heapdump file. I am trying to make a reproducer.

@kriegaex
Copy link
Contributor

kriegaex commented Apr 2, 2024

JoinPointImpl.arcIndex is a ThreadLocal<Integer>. It should consume minimal memory. How can it cause a noticeable memory leak? It should definitely be much, much better than the inheritable thread-local stack of around closures we had before. Of course, the list of around closures still exists, but it also has to, as nobody can predict which thread might need any entries from it at any given time.

@KimmingLau
Copy link
Contributor Author

KimmingLau commented Apr 3, 2024

Just as what I mentioned in code comments, ThreadLocalMap.Entry is WeakReference. When the JoinPointImpl object is collected by GC, the Entry object is still remain. If the adviced method were called frequently, it would result in accumulation of a lot of Entry object. In our own application, we found tens of thousands of Entry per Thread, which were almostly from JoinPointImpl.arcIndex.

The life cycle of ThreadLocal.Entry here should be consistent with the JoinPointImpl object, so I think we should proactively call ThreadLocal.remove() after using JoinPointImpl.arcIndex.

@KimmingLau
Copy link
Contributor Author

KimmingLau commented Apr 3, 2024

Here is a of the mentioned entrys information in heapdump:

Snipaste_2024-04-03_11-29-03

@kriegaex
Copy link
Contributor

kriegaex commented Apr 3, 2024

The life cycle of ThreadLocal.Entry here should be consistent with the JoinPointImpl object, so I think we should proactively call ThreadLocal.remove() after using JoinPointImpl.arcIndex.

Sorry, I am working on something else at the moment, I am too busy to immerse myself into the details here at the moment. Please be more specific and suggest code changes. As for those weak references, should they not be collected as well after the join point impl was collected?

Edit: Please, post screenshots inline, not as zip files. I just fixed that in your comment.

@kriegaex
Copy link
Contributor

kriegaex commented Apr 3, 2024

The problem with releasing the thread-locals is that a live thread could in principle defer proceeding indefinitely or not proceed at all. AspectJ has no way of knowing. Maybe there is a way to at least remove the thread-locals in cases where the last proceed has happened already, i.e. the index is back down to zero. I have not inspected the code yet, I am totally out of context at the moment.

kriegaex added a commit to KimmingLau/aspectj that referenced this issue Apr 7, 2024
Avoid potential ThreadLocalMap.Entry accumulation. Entry is a
WeakReference. When JoinPointImpl objects are collected by GC, Entry
instances are still be referenced by ThreadLocalMap, which leads to
memory pressure and potentially more full GCs. So, we proactively remove
ThreadLocal<Integer> arcIndex instances when arcIndex has been
decremented back to -1 per thread. This is not perfect, because not each
thread can be expected to proceed, but it should ameliorate the
situation to some degree.

Fixes eclipse-aspectj#302.

Co-authored-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Signed-off-by: KimmingLau <294001791@qq.com>
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
kriegaex added a commit to KimmingLau/aspectj that referenced this issue Apr 8, 2024
Avoid potential ThreadLocalMap.Entry accumulation. Entry is a
WeakReference. When JoinPointImpl objects are collected by GC, Entry
instances are still be referenced by ThreadLocalMap, which leads to
memory pressure and potentially more full GCs. So, we proactively remove
ThreadLocal<Integer> arcIndex instances when arcIndex has been
decremented back to -1 per thread. This is not perfect, because not each
thread can be expected to proceed, but it should ameliorate the
situation to some degree.

Fixes eclipse-aspectj#302.

Co-authored-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Signed-off-by: KimmingLau <294001791@qq.com>
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
@kriegaex kriegaex changed the title ThreadLocal Entry in JoinPointImpl is not released in time Potential ThreadLocalMap.Entry accumulation in JoinPointImpl Apr 8, 2024
@kriegaex kriegaex self-assigned this Apr 8, 2024
@kriegaex kriegaex added the enhancement New feature or request label Apr 8, 2024
@kriegaex kriegaex added this to the 1.9.22.1 milestone Apr 8, 2024
kriegaex added a commit to KimmingLau/aspectj that referenced this issue Apr 10, 2024
Relates to eclipse-aspectj#302.

Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
kriegaex added a commit to KimmingLau/aspectj that referenced this issue Apr 10, 2024
Avoid potential ThreadLocalMap.Entry accumulation. Entry is a
WeakReference. When JoinPointImpl objects are collected by GC, Entry
instances are still be referenced by ThreadLocalMap, which leads to
memory pressure and potentially more full GCs. So, we proactively remove
ThreadLocal<Integer> arcIndex instances when arcIndex has been
decremented back to -1 per thread. This is not perfect, because not each
thread can be expected to proceed, but it should ameliorate the
situation to some degree.

Fixes eclipse-aspectj#302.

Co-authored-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Signed-off-by: KimmingLau <294001791@qq.com>
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
kriegaex added a commit that referenced this issue Apr 10, 2024
Relates to #302.

Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
kriegaex added a commit that referenced this issue Apr 10, 2024
Avoid potential ThreadLocalMap.Entry accumulation. Entry is a
WeakReference. When JoinPointImpl objects are collected by GC, Entry
instances are still be referenced by ThreadLocalMap, which leads to
memory pressure and potentially more full GCs. So, we proactively remove
ThreadLocal<Integer> arcIndex instances when arcIndex has been
decremented back to -1 per thread. This is not perfect, because not each
thread can be expected to proceed, but it should ameliorate the
situation to some degree.

Fixes #302.

Co-authored-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Signed-off-by: KimmingLau <294001791@qq.com>
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants