High memory usage due to leaking ThreadLocal variables from GroovyCustomField

Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.

Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

Problem

At large JIRA instances and heavy load GroovyCustomField can leak ThreadLocal variables, that will cause high memory usage and lead to OOM.

Diagnosis

Environment

  • ScriptRunner for JIRA version 4.0 - 5.0.14

Diagnostic Steps

From heap dump you can see the following problem:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 Class Name | Shallow Heap | Retained Heap | Percentage ------------------------------------------------------------------------------------------------------------------ https-jsse-nio-10.35.136.254-8443-exec-115 Thread org.apache.tomcat.util.threads.TaskThread @ 0x35d8687b8 | 128 | 110,127,096 | 0.61% |- java.lang.ThreadLocal$ThreadLocalMap @ 0x6213b4820 | 24 | 110,121,168 | 0.61% | '- java.lang.ThreadLocal$ThreadLocalMap$Entry[32768] @ 0x360a14568 | 131,088 | 110,121,144 | 0.61% | |- java.lang.ThreadLocal$ThreadLocalMap$Entry @ 0x5937be410 | 32 | 109,711,184 | 0.61% | | '- java.util.LinkedHashMap @ 0x5937be430 | 56 | 109,711,152 | 0.61% | | |- java.util.HashMap$Node[524288] @ 0x38082b4a8 | 2,097,168 | 2,097,168 | 0.01% | | |- java.util.LinkedHashMap$Entry @ 0x4b3af5040 | 40 | 298,720 | 0.00% | | |- java.util.LinkedHashMap$Entry @ 0x393ac05e8 | 40 | 216,392 | 0.00% .... | | |- java.util.LinkedHashMap$Entry @ 0x35d057238 | 40 | 97,344 | 0.00% | | '- Total: 25 of 247,676 entries; 247,651 more | | |

Note 247k entries for ThreadLocal, and size 100MB. Referent: com.onresolve.scriptrunner.customfield.GroovyCustomField$1

Histogram:

Class Name

Objects

Shallow Heap

Retained Heap

char[]

70,599,174

9,251,242,216

>= 9,251,242,216

java.lang.String

70,488,632

1,691,727,168

>= 10,844,317,840

java.util.LinkedHashMap$Entry

20,774,537

830,981,480

>= 8,357,527,664

java.util.HashMap$Node

18,619,919

595,837,408

>= 4,209,784,280

java.util.HashMap$Node[]

2,300,341

383,801,528

>= 4,551,997,344

java.util.HashMap

2,230,648

107,071,104

>= 4,449,251,032

So we see LinkedHashMap using 8GB+ data and there are 20M objecst, same structure as above.

If we check specifically ThreadLocal, we can see that they are using 8GB+

1 2 3 4 5 6 7 8 9 Class Name | Objects | Shallow Heap | Retained Heap ------------------------------------------------------------------------------------------------------------ java.lang.ThreadLocal$ThreadLocalMap | 870 | 20,880 | >= 8,695,572,600 |- java.lang.ThreadLocal$ThreadLocalMap$Entry[] | 870 | 8,828,768 | | |- java.lang.Class | 1 | 0 | | |- java.lang.ThreadLocal$ThreadLocalMap$Entry | 206,026 | 6,592,832 | | | |- char[] | 468 | 632,624 | >= 632,624 | | |- com.atlassian.jira.web.filters.ThreadLocalQueryProfiler| 302 | 7,248 | >= 8,916,904 | | |- java.util.LinkedHashMap | 161 | 9,016 | >= 8,516,389,472

Cause

Bug in ScriptRunner:

The problem is that script field values are cached in thread locals, when there is a full reindex done for instance, there will be a long-running thread, and the script field values are not cleared from the thread local.

see related;

https://productsupport.adaptavist.com/browse/SRJIRA-2570

https://productsupport.adaptavist.com/browse/SRJIRA-551

Solution

Resolution

Upgrade ScriptRunner to 5.2.2+ version. Note it's compatible with Jira Server 7.2.0+.

Updated on April 2, 2025

Still need help?

The Atlassian Community is here for you.