Unreachable Memory not freed, Nashorn Demo

Thorsten Goetzke tg at freigmbh.de
Wed Mar 1 08:13:23 UTC 2017


Hello,

It's quite intresting the nashorn implementation seems to have changed 
significantly between java 8 and 9. In Java 8 I can not find any path to 
root. Java 9 the objects are reported weakly reachable, or reachable 
through jdk.internal.ref.CleanerImpl$PhantomCleanableRef. The resulting 
behaviour is the same, the Objects will not be cleared. In my 
environment I could run hundred's of gc, these Objects would not be 
reclaimed. In my real world application these Objects would sometimes 
get reclaimed after some unknown random actions (Executing other 
Scripts, creating new NashornScriptEngines)
I supsect these weak references are just a diversion, the gc thinks 
there is a strong chain to the LiveItems, but the chain doesn't get 
exported in the snapshot.

Best regards,
Thorsten


Am 28.02.17 um 18:56 schrieb Poonam Bajaj Parhar:
> Hello Thorsten,
>
> I ran this test program with jdk9-ea and created a Heap Dump after the
> first Full GC using -XX:+HeapDumpAfterFullGC. In that heap dump, I can
> see 2 instances of LeakImpl:
>
> Class Name       | Objects | Shallow Heap | Retained Heap
> ----------------------------------------------------------
> LeakDemo$LeakImpl|       2 |           32 |
> ----------------------------------------------------------
>
> the first one is reachable as a local variable from the main thread
> which is fine:
>
> Class Name                                    | Ref. Objects | Shallow
> Heap | Ref. Shallow Heap | Retained Heap
> ----------------------------------------------------------------------------------------------------------------
> java.lang.Thread @ 0x84f211f8 Thread          |            1 |
> 120 |                16 |           736
> '- <Java Local> LeakDemo$LeakImpl @ 0x850d89f0|            1 |
> 16 |                16 |            16
> ----------------------------------------------------------------------------------------------------------------
>
>
> the other one is reachable through the referent
> "jdk.nashorn.internal.objects.Global" of a WeakReference:
>
> Class Name              | Ref. Objects | Shallow Heap | Ref. Shallow
> Heap | Retained Heap
> -----------------------------------------------------------------------------------------------------------
> class jdk.internal.loader.ClassLoaders @ 0x84f268f8 System
> Class                                     |            1 |           16
> |                16 |            16
> '- PLATFORM_LOADER jdk.internal.loader.ClassLoaders$PlatformClassLoader
> @ 0x84f2a610                 |            1 |           96
> |                16 |       199,624
>    '- classes java.util.Vector @
> 0x850b2b70
> |            1 |           32 |                16 |        68,104
>       '- elementData java.lang.Object[640] @
> 0x850b2b90                                              |            1
> |        2,576 |                16 |        68,072
>          '- [196] class jdk.nashorn.internal.scripts.JD @
> 0x84f49960                                 |            1 |            8
> |                16 |         4,560
>             '- map$ jdk.nashorn.internal.runtime.PropertyMap @
> 0x850d4a88                            |            1 |           64
> |                16 |         4,552
>                '- protoHistory java.util.WeakHashMap @
> 0x850d5418                                    |            1 |
> 48 |                16 |         2,208
>                   '- table java.util.WeakHashMap$Entry[16] @
> 0x850d5448                              |            1 |           80
> |                16 |         2,112
>                     *'- [10] java.util.WeakHashMap$Entry @
> 0x850d5498                                |            1 |           40
> |                16 |         2,032*
>                         '- referent jdk.nashorn.internal.objects.Global
> @ 0x85137a18                 |            1 |          544
> |                16 |        39,920
>                            '- initscontext
> javax.script.SimpleScriptContext @ 0x8515c910             |            1
> |           32 |                16 |           280
>                               '- engineScope LeakDemo$SimplestBindings @
> 0x8515c930                  |            1 |           16
> |                16 |           248
>                                  '- map java.util.HashMap @
> 0x8515c940                               |            1 |           48
> |                16 |           232
>                                     '- table java.util.HashMap$Node[16]
> @ 0x8515c970                 |            1 |           80
> |                16 |           184
>                                        '- [9] java.util.HashMap$Node @
> 0x8515c9f8                    |            1 |           32
> |                16 |            48
>                                           '- value
> LeakDemo$SimplestBindings$$Lambda$118 @ 0x8515ca18|            1
> |           16 |                16 |            16
>                                              '- arg$1 LeakDemo$LeakImpl
> @ 0x8515c600                 |            1 |           16
> |                16 | 1,073,741,856
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> From the GC logs, the referent is present in an old region:
>
> [2.044s][info   ][gc,metaspace   ] GC(6) Metaspace: 13522K->13518K(1062912K)
> [2.047s][info   ][gc,start       ] GC(6) Heap Dump (after full gc)
> Dumping heap to java_pid20428.hprof ...
> Heap dump file created [1081050745 bytes in 25.084 secs]
> [27.137s][info   ][gc             ] GC(6) Heap Dump (after full gc)
> 25089.382ms
> [27.137s][info   ][gc             ] GC(6) Pause Full (Allocation
> Failure) 1028M->1028M(1970M) 25171.038ms
>
> Also:
> [10.651s][trace][gc,region] GC(6) G1HR POST-COMPACTION(OLD)
> [0x0000000085100000, 0x0000000085161f20, 0x0000000085200000]
>
> This Full GC didn't discover this WeakReference and didn't clear its
> referent. It needs to be investigated if it gets cleared and collected
> in the subsequent GCs.
>
> Thanks,
> Poonam
>
> On 2/28/2017 9:06 AM, Jenny Zhang wrote:
>> Thorsten
>>
>> Thanks very much for the micro. I have update it to
>>
>> https://bugs.openjdk.java.net/browse/JDK-8173594
>>
>> Thanks
>> Jenny
>>
>> On 2/28/2017 4:45 AM, Thorsten Goetzke wrote:
>>> Hello,
>>>
>>> Back in January i posted about Unreachable Objects not claimed by the
>>> gc, i am finally able to produce a micro, see below. When I run the
>>> class below using -Xmx4g and take a memory snaphsot (hprof or
>>> yourkit, doesnt matter), I will see 2 LeakImpl Objects. These Objects
>>> have no reported path to root, yet they won't be collected. If i
>>> lower the heap space to -Xmx2g the Application throws
>>> java.lang.OutOfMemoryError: Java heap space.
>>> @Jenny Zhang should I create a new bugreport, or will you take care
>>> of this?
>>>
>>> Best Regards,
>>> Thorsten Goetzke
>>>
>>> package de.frei.demo;
>>>
>>> import jdk.nashorn.api.scripting.NashornScriptEngine;
>>> import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
>>>
>>> import javax.script.CompiledScript;
>>> import javax.script.ScriptException;
>>> import javax.script.SimpleBindings;
>>> import java.util.function.Function;
>>>
>>>
>>> public final class LeakDemo {
>>>
>>>     private static  NashornScriptEngine ENGINE =
>>> getNashornScriptEngine();
>>>     private static CompiledScript SCRIPT;
>>>
>>>     public static void main(String[] args) throws Exception {
>>>         simulateLoad();
>>>         simulateLoad();
>>>         System.gc();
>>>         Thread.sleep(1000000);
>>>
>>>     }
>>>
>>>     private static void simulateLoad() throws ScriptException {
>>>         final CompiledScript compiledScript = getCompiledScript(ENGINE);
>>>         compiledScript.eval(new SimplestBindings(new LeakImpl()));
>>>     }
>>>
>>>     private static NashornScriptEngine getNashornScriptEngine() {
>>>         final NashornScriptEngineFactory factory = new
>>> NashornScriptEngineFactory();
>>>         final NashornScriptEngine scriptEngine =
>>> (NashornScriptEngine) factory.getScriptEngine();
>>>         return scriptEngine;
>>>     }
>>>
>>>
>>>
>>>     private static CompiledScript getCompiledScript(final
>>> NashornScriptEngine scriptEngine) throws ScriptException {
>>>         if (SCRIPT == null) {
>>>             SCRIPT = scriptEngine.compile("    var pivot =
>>> getItem(\"pivot\");");
>>>         }
>>>         return SCRIPT;
>>>     }
>>>
>>>     public  interface Leak {
>>>
>>>         LiveItem getItem(String id);
>>>     }
>>>
>>>
>>>     public static final class LeakImpl implements Leak {
>>>         private final byte[] payload = new byte[1024 * 1024 * 1024];
>>>
>>>
>>>         @Override
>>>         public LiveItem getItem(final String id) {
>>>             return new LiveItem() {
>>>             };
>>>         }
>>>
>>>
>>>     }
>>>
>>>     public interface LiveItem {
>>>     }
>>>
>>>     public static final class SimplestBindings extends SimpleBindings {
>>>         public SimplestBindings(Leak leak) {
>>>
>>>             put("getItem",(Function< String, LiveItem>) leak::getItem);
>>>         }
>>>     }
>>> }
>>>
>>> _______________________________________________
>>> hotspot-gc-use mailing list
>>> hotspot-gc-use at openjdk.java.net
>>> http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use
>>
>> _______________________________________________
>> hotspot-gc-use mailing list
>> hotspot-gc-use at openjdk.java.net
>> http://mail.openjdk.java.net/mailman/listinfo/hotspot-gc-use
>


More information about the hotspot-gc-use mailing list