Hi i was investigate multimodule project memory leek exhastion of metaspace. I was looking why build with gradle take so much metaspace and findings:
You execute in custom classloader which is ok, but its not properly shutdown jGIT so classpath is reference so classes can be unloaded because are referenced by running thread and application shutdown hook, also looking into memory dump with eclipse mat i have this allocaiton on heap which should not be there:
The classloader/component „org.sonar.classloader.ClassRealm @ 0xcacc1378“ occupies 35 571 056 (11,06 %) bytes. The memory is accumulated in one instance of „com.sonar.security.config.C“, loaded by „org.sonar.classloader.ClassRealm @ 0xcacc1378“, which occupies 33 318 960 (10,36 %) bytes.
Because com.sonar.security.config.C is propertierary or obfuscated i dont look into it.
also when i look into path to gc for sonar classloader used in i get this class which force to keep classes in metaspace:
Class Name | Shallow Heap | Retained Heap
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
org.sonarsource.scanner.api.internal.IsolatedClassloader @ 0xcc93be08 | 96 | 1 266 680
|- contextClassLoader jdk.internal.net.http.HttpClientImpl$SelectorManager @ 0xc42bb518 HttpClient-2-SelectorManager JNI Global, Thread| 144 | 4 160
|- contextClassLoader java.lang.Thread @ 0xc43679f0 OkHttp TaskRunner JNI Global, Thread | 112 | 272
|- contextClassLoader okio.AsyncTimeout$Watchdog @ 0xc4368340 Okio Watchdog JNI Global, Thread | 112 | 240
|- <classloader> class okio.AsyncTimeout$Watchdog @ 0xc43682b8 | 8 | 32
|- <classloader> class okio.AsyncTimeout @ 0xcc2b3780 | 32 | 112
|- <classloader> class okio.AsyncTimeout$Companion @ 0xcc2b3a00 | 8 | 32
|- <classloader> class okhttp3.internal.concurrent.TaskRunner @ 0xcc6ceed0 | 16 | 88
|- <classloader> class okhttp3.internal.concurrent.TaskRunner$RealBackend @ 0xcc6cf0b8 | 8 | 40
|- <classloader> class okhttp3.internal.concurrent.TaskRunner$runnable$1 @ 0xcc6cf508 | 8 | 40
|- <classloader> class okio.SocketAsyncTimeout @ 0xcc813828 | 8 | 40
|- classloader java.security.ProtectionDomain @ 0xc4374d68 | 40 | 656
|- <classloader> class okhttp3.internal.Util$$Lambda$4215+0x0000027e118ecc80 @ 0xcc6cf240 | 0 | 0
|- <classloader> class okhttp3.internal.concurrent.TaskQueue @ 0xcc6cf5a8 | 8 | 72
|- <classloader> class org.eclipse.jgit.lib.RepositoryCache$$Lambda$4374+0x0000027e11a95190 @ 0xc429a528 | 0 | 0
'- <classloader> class org.eclipse.jgit.lib.internal.WorkQueue$2 @ 0xccb143f0 | 0 | 0
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
I suggest that you fix embeded scanner that can be runned 100 times on simple java projects which resides in git or you add option to execute for each module as separated process so you dont polute gradle daemon memory.