# How JavaConcurrent work in multithreading

**URL:** <https://discuss.elastic.co/t/how-javaconcurrent-work-in-multithreading/275556>\
**Category:** APM\
**Tags:** java\
**Created:** [June 10, 2021, 11:06am UTC](https://discuss.elastic.co/t/how-javaconcurrent-work-in-multithreading/275556 "2021-06-10T11:06:34Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![sadu](https://avatars.discourse-cdn.com/v4/letter/s/4bbf92/32.png) [@sadu](https://discuss.elastic.co/u/sadu)\
**Post date:** [June 10, 2021, 11:06am UTC](https://discuss.elastic.co/t/how-javaconcurrent-work-in-multithreading/275556/1 "2021-06-10T11:06:34Z")

</div>

**Kibana version** :

# 7.10.2

**Elasticsearch version** :

# 7.10.2

**APM Server version** :

1.21.0

**APM Agent language and version** :  
Java  
**Browser version** :  
Chrome 79.0.3945.117  
**Original install method (e.g. download page, yum, deb, from source, etc.) and version** :  
download page and local setup  
**Fresh install or upgraded from other version?**  
No

\*\*

Hello,  
This question is related with other [topic](https://discuss.elastic.co/t/httpurlconnectioninstrumentation-not-work-when-use-in-different-thread/266560).

I would like to add "APM context" in custom multithread solution.  
I check how that was done in "apm-java-concurrent-plugin" plugin. There is a class JavaConcurrent that add context to Callable or Runnable.

In this plugin there is a instrumentation class for executor co.elastic.apm.agent.concurrent.ExecutorInstrumentation

```auto

    public static class ExecutorRunnableInstrumentation extends ExecutorInstrumentation {

        @Nullable
        @AssignTo.Argument(0)
        @Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
        public static Runnable onExecute(@Advice.This Executor thiz,
                                         @Advice.Argument(0) @Nullable Runnable runnable) {
            if (ExecutorInstrumentation.isExcluded(thiz)) {
                return runnable;
            }
            return JavaConcurrent.withContext(runnable, tracer);
        }

        @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class, inline = false)
        public static void onExit(@Nullable @Advice.Thrown Throwable thrown,
                                   @Advice.Argument(value = 0) @Nullable Runnable runnable) {
            JavaConcurrent.doFinally(thrown, runnable);
        }     
    }

```

Code in onExecute `JavaConcurrent.withContext(runnable, tracer)` put object into `WeakConcurrentMap`

In onExit method this class call `JavaConcurrent.doFinally(thrown, runnable);` In this method object added by `withContext` metod is removed only when `Throwable` object is not null. Question is what about calls without error ? When such objects will be removed?

```auto
    public static void doFinally(@Nullable Throwable thrown, @Nullable Object contextObject) {
        needsContext.set(Boolean.TRUE);
        if (thrown != null && contextObject != null) {
            removeContext(contextObject);
        }
    }

```

I use JavaConcurrent in my plugin, but from debug I see that WeakConcurrentMap is not cleaning and even when thread stop working, object stay in collection.

Thank you for help.

---

<div class="post-metadata">

**Author:** ![Eyal\_Koren](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/eyal_koren/32/36830_2.png) [@Eyal\_Koren](https://discuss.elastic.co/u/Eyal_Koren)\
**Post date:** [June 14, 2021, 7:08am UTC](https://discuss.elastic.co/t/how-javaconcurrent-work-in-multithreading/275556/3 "2021-06-14T07:08:34Z")

</div>

Please see where this `JavaConcurrent` usage is done - the **submission** of a `Runnable` or `Callable` before execution. This removal of the context through `doFinally` is only for handling cases where the submission itself fails, not the actual execution. When submission succeeds, the context will be removed at the end of the `run()`/`call()` execution. If you apply this instrumentation to somewhere else in your code, right after the `Runnable`/`Callable` is created **and still on the creating thread** , and before the forked thread starts executing it, it should work.

However, since this is an internal API, its stability is not guaranteed.  
Instead, consider using an [external plugin](https://github.com/elastic/apm-agent-java/tree/master/integration-tests/external-plugin-test). You would need to use your own implementation of `JavaConcurrent`, by using only SDK and public APIs, which are much more stable. I believe you should get what you need for that:

- `co.elastic.apm.agent.sdk.DynamicTransformer#ensureInstrumented()`
- `co.elastic.apm.agent.sdk.weakmap.WeakMapSupplier`
- public API for starting/activating spans

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [July 5, 2021, 3:09am UTC](https://discuss.elastic.co/t/how-javaconcurrent-work-in-multithreading/275556/4 "2021-07-05T03:09:01Z")

</div>

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.
