<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">What you are suggesting is
what we call "specifying the implementation", which is generally
not a very good idea. <br>
<br>
The specification for these methods says "returns a String
<with the following properties>". That's a good
specification! It says what you can expect from the result. It
says nothing about the identity of the returned object, whether
it is interned, whether it is aliased, etc. This is by design.
Specifying the implementation not only robs future implementers
of the ability to improve the implementation (which in turn
improves all the code that uses it, without having to even
recompile), and encourages people to do questionable things like
make assumptions about the identity of the returned String. <br>
<br>
To describe this as "non-deterministic" is an abuse of the
term. What is going on here is that the specification makes
certain promises, and multiple implementations choose different
ways to get there (and any given implementation could choose
different ways in different points in time.) Similarly,
describing it as "inconsistent" is also an abuse; no one
promised a non-aliased object. <br>
<br>
If your code wants to make assumptions about interning or lack
of aliasing, you should call "new String(s)". <br>
</font></font><br>
<div class="moz-cite-prefix">On 6/19/2022 11:29 PM, Sasi Peri wrote:<br>
</div>
<blockquote type="cite" cite="mid:CALR+58k+EYsAsLtTA9SNhYRGFq4pxkS8RoemFGVAnxR7zF=dvQ@mail.gmail.com">
<div dir="ltr">Hello,
<div><br>
</div>
<div>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b>Issue
details</b></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">toLower()
and toUpper() return a new String object sometimes
and sometimes a string literal, based on the input string
type (and also sometimes
based on the VM/jdk type)</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"> </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">For
example</p>
<p class="gmail-MsoListParagraphCxSpFirst" style="margin:0in
0in 0in 0.5in;font-size:12pt;font-family:Calibri,sans-serif">-<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times
New Roman"">
</span>HotSpot VM, If the input is a string literal,
which *already* has all “lower case letters”, toLower would
return the same
string literal, if not it will convert all letters to lower
and returns a new
String() object.</p>
<p class="gmail-MsoListParagraphCxSpLast" style="margin:0in
0in 0in 0.5in;font-size:12pt;font-family:Calibri,sans-serif">-<span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times
New Roman"">
</span>However, openJ9 (e.g. IBM jdk8 ditsro, ) always
returns a new String object not a literal.</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"> </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">This
behavior is non deterministic, inconsistent, you cannot
always predict if the outcome is a new string object OR an
interned string from
pool (particularly from unit testing stand point).</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"> </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b>Sample
code to show case above behavior</b></p>
<table class="gmail-MsoTableGrid" style="border-collapse:collapse;border:none" cellspacing="0" cellpadding="0" border="1">
<tbody>
<tr>
<td style="width:467.5pt;border:1pt solid
windowtext;padding:0in 5.4pt" width="623" valign="top">
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">package</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> com.bugs;</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">import</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> java.util.Locale;</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo"> </span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">public</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> </span><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">class</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> TestStringFunction
</span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black">{</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)"> public</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> </span><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">static</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> </span><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">void</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> main(String </span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">args</span><span style="font-size:9pt;font-family:Menlo;color:black">[])</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> {</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> String </span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s1</span><span style="font-size:9pt;font-family:Menlo;color:black"> = </span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"abc"</span><span style="font-size:9pt;font-family:Menlo;color:black">;</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> String </span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s2</span><span style="font-size:9pt;font-family:Menlo;color:black"> = </span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"ABC"</span><span style="font-size:9pt;font-family:Menlo;color:black">;</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> System.</span><b><i><span style="font-size:9pt;font-family:Menlo;color:rgb(0,0,192)">out</span></i></b><span style="font-size:9pt;font-family:Menlo;color:black">.println(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"----- case:
when string already lower ----------"</span><span style="font-size:9pt;font-family:Menlo;color:black">);</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><i><span style="font-size:9pt;font-family:Menlo;color:black;background:rgb(212,212,212)">
testIfEqualsLower</span></i><span style="font-size:9pt;font-family:Menlo;color:black">(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s1</span><span style="font-size:9pt;font-family:Menlo;color:black">);</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> System.</span><b><i><span style="font-size:9pt;font-family:Menlo;color:rgb(0,0,192)">out</span></i></b><span style="font-size:9pt;font-family:Menlo;color:black">.println(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"----- case:
when string with upper case ----------"</span><span style="font-size:9pt;font-family:Menlo;color:black">);</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><i><span style="font-size:9pt;font-family:Menlo;color:black;background:rgb(212,212,212)">
testIfEqualsLower</span></i><span style="font-size:9pt;font-family:Menlo;color:black">(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s2</span><span style="font-size:9pt;font-family:Menlo;color:black">);</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> }</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)"> private</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> </span><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">static</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> </span><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)">void</span></b><span style="font-size:9pt;font-family:Menlo;color:black"> <span style="background:rgb(212,212,212)">testIfEqualsLower</span>(String
</span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s</span><span style="font-size:9pt;font-family:Menlo;color:black">) </span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> {</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)"> if</span></b><span style="font-size:9pt;font-family:Menlo;color:black">(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s</span><span style="font-size:9pt;font-family:Menlo;color:black">.toLowerCase() == </span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"abc"</span><span style="font-size:9pt;font-family:Menlo;color:black">)</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> {</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> System.</span><b><i><span style="font-size:9pt;font-family:Menlo;color:rgb(0,0,192)">out</span></i></b><span style="font-size:9pt;font-family:Menlo;color:black">.println(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"YES -
literal"</span><span style="font-size:9pt;font-family:Menlo;color:black">);</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> }</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)"> if</span></b><span style="font-size:9pt;font-family:Menlo;color:black">(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(106,62,62)">s</span><span style="font-size:9pt;font-family:Menlo;color:black">.toLowerCase().equals(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"abc"</span><span style="font-size:9pt;font-family:Menlo;color:black">))</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> {</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> System.</span><b><i><span style="font-size:9pt;font-family:Menlo;color:rgb(0,0,192)">out</span></i></b><span style="font-size:9pt;font-family:Menlo;color:black">.println(</span><span style="font-size:9pt;font-family:Menlo;color:rgb(42,0,255)">"YES –
equals func"</span><span style="font-size:9pt;font-family:Menlo;color:black">);</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> }</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> </span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black"> }</span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt">}</span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt"> </span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt"> </span></p>
</td>
</tr>
<tr>
<td style="width:467.5pt;border-right:1pt solid
windowtext;border-bottom:1pt solid
windowtext;border-left:1pt solid
windowtext;border-top:none;padding:0in 5.4pt" width="623" valign="top">
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><u><span style="font-size:9pt;font-family:Menlo;color:rgb(192,0,0)">Out put</span></u></b></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><u><span style="font-size:9pt;font-family:Menlo;color:rgb(192,0,0)"><span style="text-decoration-line:none"> </span></span></u></b></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black">----- case: when
string already lower ----------</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black">YES - literal</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black">YES – equals func</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo"> </span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black">----- case: when
string with upper case ----------</span><span style="font-size:9pt;font-family:Menlo"></span></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:9pt;font-family:Menlo;color:black">YES - equals func</span><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)"></span></b></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b><span style="font-size:9pt;font-family:Menlo;color:rgb(127,0,85)"> </span></b></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"> </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b>Why
this could be an issue or bug prone?</b></p>
<p class="gmail-MsoListParagraphCxSpFirst" style="margin:0in
0in 0in 0.5in;font-size:12pt;font-family:Calibri,sans-serif"><span style="font-size:12pt">-</span><span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times
New Roman"">
</span><span style="font-size:12pt">Suppose an unit test is
written, for a method doAThing(),
that has toLower/Upper conversions in the middle of the
code somewhere, and
apply logic based on that.</span><br>
<span style="font-size:12pt">-</span><span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times
New Roman"">
</span><span style="font-size:12pt">Though general guidance
to compare unknown
string (types) is always using equals, sometimes
developers can make a mistake
(i.e. suppose they used == in a unit test)</span><br>
<span style="font-size:12pt">-</span><span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times
New Roman"">
</span><span style="font-size:12pt">If the code review did
not catch it, this behavior
can cause all unit tests passed, as long unit test is
written with “small case
string” as input.</span><br>
<span style="font-size:12pt">-</span><span style="font-variant-numeric:normal;font-variant-east-asian:normal;font-stretch:normal;font-size:7pt;line-height:normal;font-family:"Times
New Roman"">
</span><span style="font-size:12pt">It could potentially
make it to prod, and can be
realized only when it hits a case </span>when input<span style="font-size:12pt"> string has all uppercase OR mixed
case letters, which could be after multiple sprints, at
the point not easily detectable.</span><br>
</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"> </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><b>Suggestion</b></p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">It
would be great if we always can make a new String() and
return always a String object not an interned string
sometimes, as openJ9/ibm
does (with some jdk versions). </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">It
may not be good idea, to always return “.interned” value
and fill up the intern pool, for these short-lived objects
(as they are most times).</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"> </p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">If
this is agreed/approved, I can make a change and commit.</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif"><br>
</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">Regards</p>
<p class="MsoNormal" style="margin:0in;font-size:12pt;font-family:Calibri,sans-serif">-
SP</p>
</div>
</div>
</blockquote>
<br>
</body>
</html>