Groovy getProperties () call getter call for non-existent attribute more than 1000 times

Get into it by refactoring. The calls to getProperties () made our CPU use a spike. We found that if you have a getter without an associated attribute when you call getProperties (), then getter is called more than 1000 times. The fix / workaround is obvious, and we know that it has something to do with metaprogramming, but why is this happening (what's the point in the groovy source)? See the groovy script code below:

class tester { int count = 0 public getVar() { println count++ + " getVar() called!" return var } } def t = new tester() t.getProperties() println "done!" 

You should see getVar () more than 1000 times. 1068 to be exact for us.

+5
source share
1 answer

The question may have already been answered in the comments, but I delved a little deeper to answer the question "what is the point in the original part of groovy.

When you call getProperties() on a tester groovy instance, it does its magic and finally calls DefaultGroovyMethods#getProperties(Object) , which (in groovy 2.4.7) looks like this:

 public static Map getProperties(Object self) { List<PropertyValue> metaProps = getMetaPropertyValues(self); // 1 Map<String, Object> props = new LinkedHashMap<String, Object>(metaProps.size()); for (PropertyValue mp : metaProps) { try { props.put(mp.getName(), mp.getValue()); // 2 } catch (Exception e) { LOG.throwing(self.getClass().getName(), "getProperty(" + mp.getName() + ")", e); } } return props; } 

Firstly, groovy defines the meta-properties of a given object (see 1). This will return three properties:

  • var : only getter ( getVar() ), no setter, no field
  • class : only getter (inherited from Object ), no setter, no field
  • count : getter, setter (both generated by Groovy) and field

You can easily verify this by calling t.getMetaPropertyValues() .

Then groovy tries to get the current value of each property and puts it on the map (see 2). When it reaches var , it remembers that var has a getter (namely getVar() ) and calls it. However, getVar() returns var again. For Groovy, this is the same property as in the first step. Once again, he calls it getter getVar() and an infinite loop begins.

At some point, depending on the JVM, this leads to a StackOverflowError , which is exactly this site: -D

0
source

Source: https://habr.com/ru/post/1241150/


All Articles