You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by "Hans-Peter Stoerr (Jira)" <ji...@apache.org> on 2020/03/31 11:23:00 UTC

[jira] [Updated] (SLING-9312) Bug in LazyBindings.entrySet: hashCode of binding values is calculated

     [ https://issues.apache.org/jira/browse/SLING-9312?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Hans-Peter Stoerr updated SLING-9312:
-------------------------------------
    Description: 
The method entrySet in org.apache.sling.api.scripting.LazyBindings currently has a bug that forces the hashCode of the entry values in Bindings are calculated in each HTL request, when it should only be the hashCode of the keys - if at all. This can be a performance problem if the value is e.g. a large map, in our (complicated) case this even got us a StackOverflowError.

The problematic code is:
{code:java}
    public Set<Entry<String, Object>> entrySet() {
        HashSet<Entry<String, Object>> entrySet = new HashSet<>(super.entrySet());
        for (Map.Entry supplierEntry : suppliers.entrySet()) {
            entrySet.add(supplierEntry);
        }
        return Collections.unmodifiableSet(entrySet);
    } {code}
Since the entries are put together in a HashSet, each add will calculate the hashCode of the entry - which sums the hashCode of the key *and the value* of each binding entry. I suggest to replace this with a HashMap and return it's entrySet. Another problem is that this could return several entries for the same key, which is probably not intended..

In case you are wondering, this is called in every HTL request like this:
{code:java}
         at java.base/java.util.HashSet.add(HashSet.java:220)
          at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:336)
          at java.base/java.util.HashSet.<init>(HashSet.java:120)
          at org.apache.sling.api.scripting.LazyBindings.entrySet(LazyBindings.java:117) [org.apache.sling.api:2.21.0]
          at org.apache.sling.api.scripting.LazyBindings.putAll(LazyBindings.java:87) [org.apache.sling.api:2.21.0]
          at org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript.eval(SightlyCompiledScript.java:50) [org.apache.sling.scripting.sightly:1.2.0.0]
          at org.apache.sling.scripting.core.impl.DefaultSlingScript.call(DefaultSlingScript.java:386) [org.apache.sling.scripting.core:2.1.0]
          at org.apache.sling.scripting.core.impl.DefaultSlingScript.eval(DefaultSlingScript.java:184) [org.apache.sling.scripting.core:2.1.0]
          at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:491) [org.apache.sling.scripting.core:2.1.0]
          at org.apache.sling.engine.impl.request.RequestData.service(RequestData.java:552) [org.apache.sling.engine:2.6.20]
          at org.apache.sling.engine.impl.filter.SlingComponentFilterChain.render(SlingComponentFilterChain.java:44) [org.apache.sling.engine:2.6.20] {code}
 

 

  was:
The method entrySet in org.apache.sling.api.scripting.LazyBindings currently has a bug that forces the hashCode of the entry values in Bindings are calculated in each HTL request, when it should only be the hashCode of the keys - if at all. This can be a performance problem if the value is e.g. a large map, in our (complicated) case this even got us a StackOverflowError.

The problematic code is:
{code:java}
    public Set<Entry<String, Object>> entrySet() {
        HashSet<Entry<String, Object>> entrySet = new HashSet<>(super.entrySet());
        for (Map.Entry supplierEntry : suppliers.entrySet()) {
            entrySet.add(supplierEntry);
        }
        return Collections.unmodifiableSet(entrySet);
    } {code}
Since the entries are put together in a HashSet, each add will calculate the hashCode of the entry - which sums the hashCode of the key *and the value* of each binding entry. I suggest to replace this with a HashMap and return it's entrySet.

In case you are wondering, this is called in every HTL request like this:
{code:java}
         at java.base/java.util.HashSet.add(HashSet.java:220)
          at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:336)
          at java.base/java.util.HashSet.<init>(HashSet.java:120)
          at org.apache.sling.api.scripting.LazyBindings.entrySet(LazyBindings.java:117) [org.apache.sling.api:2.21.0]
          at org.apache.sling.api.scripting.LazyBindings.putAll(LazyBindings.java:87) [org.apache.sling.api:2.21.0]
          at org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript.eval(SightlyCompiledScript.java:50) [org.apache.sling.scripting.sightly:1.2.0.0]
          at org.apache.sling.scripting.core.impl.DefaultSlingScript.call(DefaultSlingScript.java:386) [org.apache.sling.scripting.core:2.1.0]
          at org.apache.sling.scripting.core.impl.DefaultSlingScript.eval(DefaultSlingScript.java:184) [org.apache.sling.scripting.core:2.1.0]
          at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:491) [org.apache.sling.scripting.core:2.1.0]
          at org.apache.sling.engine.impl.request.RequestData.service(RequestData.java:552) [org.apache.sling.engine:2.6.20]
          at org.apache.sling.engine.impl.filter.SlingComponentFilterChain.render(SlingComponentFilterChain.java:44) [org.apache.sling.engine:2.6.20] {code}
 

 


> Bug in LazyBindings.entrySet: hashCode of binding values is calculated
> ----------------------------------------------------------------------
>
>                 Key: SLING-9312
>                 URL: https://issues.apache.org/jira/browse/SLING-9312
>             Project: Sling
>          Issue Type: Bug
>          Components: API
>    Affects Versions: API 2.21.0, API 2.22.2
>            Reporter: Hans-Peter Stoerr
>            Priority: Minor
>
> The method entrySet in org.apache.sling.api.scripting.LazyBindings currently has a bug that forces the hashCode of the entry values in Bindings are calculated in each HTL request, when it should only be the hashCode of the keys - if at all. This can be a performance problem if the value is e.g. a large map, in our (complicated) case this even got us a StackOverflowError.
> The problematic code is:
> {code:java}
>     public Set<Entry<String, Object>> entrySet() {
>         HashSet<Entry<String, Object>> entrySet = new HashSet<>(super.entrySet());
>         for (Map.Entry supplierEntry : suppliers.entrySet()) {
>             entrySet.add(supplierEntry);
>         }
>         return Collections.unmodifiableSet(entrySet);
>     } {code}
> Since the entries are put together in a HashSet, each add will calculate the hashCode of the entry - which sums the hashCode of the key *and the value* of each binding entry. I suggest to replace this with a HashMap and return it's entrySet. Another problem is that this could return several entries for the same key, which is probably not intended..
> In case you are wondering, this is called in every HTL request like this:
> {code:java}
>          at java.base/java.util.HashSet.add(HashSet.java:220)
>           at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:336)
>           at java.base/java.util.HashSet.<init>(HashSet.java:120)
>           at org.apache.sling.api.scripting.LazyBindings.entrySet(LazyBindings.java:117) [org.apache.sling.api:2.21.0]
>           at org.apache.sling.api.scripting.LazyBindings.putAll(LazyBindings.java:87) [org.apache.sling.api:2.21.0]
>           at org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript.eval(SightlyCompiledScript.java:50) [org.apache.sling.scripting.sightly:1.2.0.0]
>           at org.apache.sling.scripting.core.impl.DefaultSlingScript.call(DefaultSlingScript.java:386) [org.apache.sling.scripting.core:2.1.0]
>           at org.apache.sling.scripting.core.impl.DefaultSlingScript.eval(DefaultSlingScript.java:184) [org.apache.sling.scripting.core:2.1.0]
>           at org.apache.sling.scripting.core.impl.DefaultSlingScript.service(DefaultSlingScript.java:491) [org.apache.sling.scripting.core:2.1.0]
>           at org.apache.sling.engine.impl.request.RequestData.service(RequestData.java:552) [org.apache.sling.engine:2.6.20]
>           at org.apache.sling.engine.impl.filter.SlingComponentFilterChain.render(SlingComponentFilterChain.java:44) [org.apache.sling.engine:2.6.20] {code}
>  
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)