<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    Hi Eirik,<br>
    <br>
    Yes, its a long standing and inconsistent area of deferred
    maintenance.<br>
    Most of the individual cases are not used enough to warrant making
    the (in many cases) incompatible change and breaking some
    application/library somewhere.<br>
    <br>
    Interesting, you did not mention Boolean.getBoolean(String name)
    whose behavior isn't the most useful.<br>
    In particular, it returns true only if the value is "true" (case
    insensitive).<br>
    <br>
    From a usability point of view, it should be true if the Property is
    present and either "true" or empty.<br>
    It should be possible to enable using just '-Dname'.<br>
    <br>
    <br>
    A related problem is the naming and semantics of the property, there
    a number of places where to enable a function you have to set a
    "disableXXX" property to false.  That makes comprehension harder.<br>
    <br>
    Common utility methods might be a small code cleanup but aligning
    all uses might have a very small payback for the possible
    incompatibilties.<br>
    <br>
    Regards, Roger<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 12/4/24 9:47 AM, Eirik Bjørsnøs
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CA+pBWhsR1u9EZX3p9-iu6iC=t9zd=Ft4-qp9+yJLLSxmiR0DwA@mail.gmail.com">
      
      <div dir="ltr">
        <div dir="ltr">
          <div>Hi,<br>
          </div>
          <div><br>
          </div>
          <div>The OpenJDK includes many boolean flags in the form of
            system properties. These toggle different behavior such as
            debug logging, verification, caching, compatibility and
            conditional features.</div>
          <div><br>
          </div>
          <div>A common interpretation is to evaluate a property as true
            if it is set and either blank or equal to "true" (ignoring
            case). This is a useful interpretation when a feature should
            usually be disabled, but you want users to enable it by
            setting a flag:</div>
          <div><br>
          </div>
          <div>Let's call this the "ifEnabled" interpretation:</div>
          <div><br>
          </div>
          <div><font face="monospace">-Dflag=true  => true</font></div>
          <div><span style="font-family:monospace">-Dflag=TRUE  =>
              true</span></div>
          <div><font face="monospace">-Dflag       => true</font></div>
          <div><font face="monospace">-Dflag=false => false </font></div>
          <div><span style="font-family:monospace">-Dflag=FALSE =>
              false </span></div>
          <div><font face="monospace">-Dflag=abc   => false</font></div>
          <div><span style="font-family:monospace">-Dother      =>
              false</span></div>
          <div><br>
          </div>
          <div>MacOSXFileSystem:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">final String name =
              PROPERTY_NORMALIZE_FILE_PATHS;<br>
              String value = System.getProperty(name);<br>
              NORMALIZE_FILE_PATHS = (value != null)<br>
                  && ("".equals(value) ||
              Boolean.parseBoolean(value));</font></blockquote>
          <div><br>
          </div>
          <div>The same logic is implemented in a number of different
            ways, see for example:</div>
          <div><br>
          </div>
          <div>IPAddressUtil:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">var value =
              System.getProperty(DELAY_URL_PARSING_SP, "false");<br>
              DELAY_URL_PARSING_SP_VALUE = value.isEmpty()<br>
                      || Boolean.parseBoolean(value);</font></blockquote>
          <div><br>
          </div>
          <div>It can also be used to conditionally disable a feature: </div>
          <div><br>
          </div>
          <div>ZipFile:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">boolean result;<br>
              String value =
              System.getProperty("jdk.util.zip.disableZip64ExtraFieldValidation");<br>
              if (value == null) {<br>
                  result = false;<br>
              } else {<br>
                  result = value.isEmpty() ||
              value.equalsIgnoreCase("true");<br>
              }<br>
              return result;</font></blockquote>
          <div><br>
          </div>
          <div>However, sometimes the logic is inverted (what we really
            want below is USE_FAST_PATH = !flagSet): </div>
          <div><br>
          </div>
          <div>SystemModuleFinders:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">String value =
              System.getProperty("jdk.system.module.finder.disableFastPath");<br>
              if (value == null) {<br>
                  USE_FAST_PATH = true;<br>
              } else {<br>
                  USE_FAST_PATH = !value.isEmpty() &&
              !Boolean.parseBoolean(value);<br>
              }</font> </blockquote>
          <div><br>
          </div>
          <div>Another variant of interpretation flips the meaning of
            null and empty values. Under this interpretation, a flag
            evaluates to true when the flag is not set (value is null)
            and to false when the flag is set but empty. Presumably,
            this is useful when you want a feature to be enabled by
            default, but you need a way to disable it by setting the
            flag to "false"</div>
          <div><br>
          </div>
          <div>Let's call this the "unlessDisabled" interpretation:</div>
          <div><br>
          </div>
          <div>
            <div><font face="monospace">-Dflag=true  => true</font></div>
            <div><span style="font-family:monospace">-Dflag=TRUE  =>
                true</span></div>
            <div><font face="monospace">-Dflag       => false</font></div>
            <div><font face="monospace">-Dflag=false => false </font></div>
            <div><span style="font-family:monospace">-Dflag=FALSE =>
                false </span></div>
            <div><font face="monospace">-Dflag=abc   => false</font></div>
            <div><span style="font-family:monospace">-DnotFlag    =>
                true</span></div>
          </div>
          <div><br>
          </div>
          <div>Switching the meaning of null seems useful, as it allows
            defining a different default value when the flag is not set.</div>
          <div><br>
          </div>
          <div>Switching the meaning of empty seems more questionable.
            Why should the following evaluate to false? </div>
          <div><br>
          </div>
          <div><font face="monospace">-Djdk.preserveScopedValueCache</font></div>
          <div><font face="monospace"><br>
            </font></div>
          <div><font face="arial, sans-serif">Likewise, why should the
              following evaluate to false given that the default if not
              set is true?</font></div>
          <div><font face="arial, sans-serif"><br>
            </font></div>
          <div><span style="font-family:monospace">-Djdk.preserveScopedValueCache=abc</span></div>
          <div><br>
          </div>
          <div>I'm wondering if such use cases would have been better
            served by a "not set to false" interpretation:</div>
          <div><br>
          </div>
          <div>
            <div>
              <div><font face="monospace">-Dflag=true  => true</font></div>
              <div><span style="font-family:monospace">-Dflag=TRUE 
                  => true</span></div>
              <div><font face="monospace">-Dflag       => true</font></div>
              <div><font face="monospace">-Dflag=false => false </font></div>
              <div><span style="font-family:monospace">-Dflag=FALSE
                  => false </span></div>
              <div><font face="monospace">-Dflag=abc   => true</font></div>
              <div><span style="font-family:monospace">-DnotFlag   
                  => true</span></div>
            </div>
          </div>
          <div><br>
          </div>
          <div>Some examples of this logic:</div>
          <div><br>
          </div>
          <div>Continuation.java:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">String value =
              System.getProperty("jdk.preserveScopedValueCache");<br>
              PRESERVE_SCOPED_VALUE_CACHE = (value == null) ||
              Boolean.parseBoolean(value);</font></blockquote>
          <div><br>
          </div>
          <div>HttpClient.java:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">String keepAlive =
              props.getProperty("http.keepAlive");<br>
              if (keepAlive != null) {<br>
                  keepAliveProp = Boolean.parseBoolean(keepAlive);<br>
              } else {<br>
                  keepAliveProp = true;<br>
              }</font></blockquote>
          <div><br>
          </div>
          <div>Complicating the above is the fact that not all  "true"
            or "false" comparisons ignores case:</div>
          <div><br>
          </div>
          <div>InetAddress.java:</div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">PREFER_IPV4_STACK_VALUE =
              System.getProperty("java.net.preferIPv4Stack");<br>
            </font></blockquote>
          <div>.. </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><font face="monospace">if
              ("true".equals(PREFER_IPV4_STACK_VALUE) &&
              ipv4Available) {<br>
                  return LookupPolicy.of(IPV4);<br>
              }</font></blockquote>
          <div><br>
          </div>
          <div>The sum of all this "interpretation-of-flags" logic was a
            bit messy and inconsistent before the JEP-486 cleanups.
            After the SecurityManager cleanups, it's becoming
            increasingly evident that there is a good amount of
            accidental complexity in this area. </div>
          <div><br>
          </div>
          <div>
            <div>The analysis required just to prepare this email felt
              surprisingly difficult. One would think programmers can
              reason about simple boolean arithmetic, but after looking
              at this aspect of the code base for a while, I quickly
              felt the need for a banana break :-)</div>
          </div>
          <div>
            <div><br>
            </div>
          </div>
          <div>I guess there is also an underlying usability question
            here: Would users prefer using the "ifEnabled"
            interpretation to configure a "featureDisabled" flag, or
            would it be better to use an "unlessDisabled" interpretation
            on a "featureEnabled" flag. Looking at the OpenJDK code
            base, it's obvious that developers are not in agreement
            about this question, leading to inconsistent treatment of
            flags. (Personally, I much prefer "enabled=false" over
            "disabled=true")</div>
          <div><br>
          </div>
          <div>
            <div>Perhaps we should introduce some "Flags" utility with
              functions for a small set of standard interpretations?
              Then new code could mostly use that, and existing code
              could gradually move over to match standard
              interpretations after carefully reviewing behavioral
              impact?</div>
            <div><br>
            </div>
          </div>
          <div>Any ideas, feedback, questions?</div>
          <div><br>
          </div>
          <div>Thanks,</div>
          <div>Eirik.</div>
        </div>
      </div>
    </blockquote>
    <br>
  </body>
</html>