Uploaded image for project: 'Red Hat Decision Manager'
  1. Red Hat Decision Manager
  2. RHDM-1854

VariableSpaceModel#allVars field should be defined as "final".

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • 7.12.1.GA
    • 7.9.0.GA
    • BRE
    • False
    • False
    • Release Notes
    • CR1
    • -
    • 2021 Week 49-51 (from Dec 6th)

    Description

      allVars field in org.mvel2.util.VariableSpaceModel class should be defined as final.

      [Background]

      It is reported that NPE like (*1) rarely occurs at (*2-1) in org.mvel2.util.SimpleVariableSpaceModel#createFactory(Object[]) when workload is very high.

      (*1) NullPointerException

      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26) Caused by: java.lang.NullPointerException
      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26)    at org.mvel2.util.SimpleVariableSpaceModel.createFactory(SimpleVariableSpaceModel.java:18)
      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26)    at org.drools.core.base.mvel.MVELCompilationUnit.createFactory(MVELCompilationUnit.java:298)
      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26)    at org.drools.core.rule.constraint.MvelConditionEvaluator.evaluate(MvelConditionEvaluator.java:117)
      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26)    at org.drools.core.rule.constraint.MvelConditionEvaluator.evaluate(MvelConditionEvaluator.java:98)
      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26)    at org.drools.core.rule.constraint.MvelConstraint.evaluate(MvelConstraint.java:275)
      2021-09-12 03:29:44.164 ERROR [stderr] (default task-26)    ... 153 more
      

      (*2) Excerpt from org/mvel2/util/SimpleVariableSpaceModel.java

          :
          :
      12  public class SimpleVariableSpaceModel extends VariableSpaceModel {
      13    public SimpleVariableSpaceModel(String[] varNames) {
      14      this.allVars = varNames;
      15    }
      16  
      17    public VariableResolverFactory createFactory(Object[] vals) {
      18      VariableResolver[] resolvers = new VariableResolver[allVars.length];    <---------- (*2-1) NPE occurs here.
      19      for (int i = 0; i < resolvers.length; i++) {
      20        if (i >= vals.length) {
      21          resolvers[i] = new SimpleValueResolver(null);
      22        }
      23        else {
      24          resolvers[i] = new IndexVariableResolver(i, vals);
      25        }
      26      }
      27  
      28      return new IndexedVariableResolverFactory(allVars, resolvers);
      29    }
      30  }
          :
          :
      

      allVars field in VariableSpaceModel class is currently defined without final. According to (*3) and (*4) in [1], a non-final field is not guaranteed to be seen its expected value after the object's constructor finishes, and it may be related to the NPE issue above.

      allVars is a field which does not need to be modified after initialization, so it should be defined as final to eliminate the possibility to cause the NPE issue due to being non-final field.

      [1] The Java Language Specification (Java SE 11 Edition) - 17.5. final Field Semantics
      https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.5

      (Excerpt from [1])

      17.5. final Field Semantics
      :
      :
      Example 17.5-1. final Fields In The Java Memory Model
      The program below illustrates how final fields compare to normal fields.

      class FinalFieldExample { 
          final int x;
          int y; 
          static FinalFieldExample f;
      
          public FinalFieldExample() {
              x = 3; 
              y = 4; 
          } 
      
          static void writer() {
              f = new FinalFieldExample();
          } 
      
          static void reader() {
              if (f != null) {
                  int i = f.x;  // guaranteed to see 3  
                  int j = f.y;  // could see 0            <---------- (*3)
              } 
          } 
      }
      

      The class FinalFieldExample has a final int field x and a non-final int field y. One thread might execute the method writer and another might execute the method reader.
      Because the writer method writes f after the object's constructor finishes, the reader method will be guaranteed to see the properly initialized value for f.x: it will read the value 3. However, f.y is not final; the reader method is therefore not guaranteed to see the value 4 for it. <---------- (*4)

      Attachments

        Issue Links

          Activity

            People

              mfusco@redhat.com Mario Fusco
              rhn-support-myoshida Masato Yoshida
              Daniel Rosa Daniel Rosa
              Daniel Rosa Daniel Rosa
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: