Question about final field semantic in case of a race

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Question about final field semantic in case of a race

Thomas Krieger

Hi,

I am running the following JCStressTest on a Raspberry Pi 3 with a Java(TM) SE Runtime Environment (build 1.8.0_65-b17) Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode):

@JCStressTest
@Outcome(id = "0", expect = Expect.ACCEPTABLE, desc = "Default outcome.")
@State
public class BigDecimalToString {
    private final  BigDecimal testBigDecimal = new BigDecimal("0.56");
    @Actor
    public void actor1(IntResult1 r) {
        testBigDecimal.toString().length();
    }
    @Actor
    public void actor2(IntResult1 r) {
        testBigDecimal.toString().length();
    }    
}

In about half of the iterations, I see the following Exception:
java.lang.NullPointerException
at java.lang.String.length(String.java:623)
at com.vmlens.stressTest.tests.BigDecimalToString.actor1(BigDecimalToString.java:12)
at com.vmlens.stressTest.tests.BigDecimalToString_jcstress.actor1(BigDecimalToString_jcstress.java:145)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

The NullPointerException happens at this statement: return value.length. The BigDecimal toString method caches the String leading to race:
@Override
    public String toString() {
        String sc = stringCache;
        if (sc == null)
            stringCache = sc = layoutChars(true);
        return sc;
    }
    /**
     * Used to store the canonical string representation, if computed.
     */
    private transient String stringCache;

But the field "value" of the Class String is final. So my question:
Is the behavior of the test the expected result?  The JLS spec (17.5) states: "A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.". In my test, a thread can get a reference to a String which has not been completely initialized and the NullPointerException is a
consequence of the Race. Or, because of the final field, all threads should have only seen an initialized value?


Thank you very much
Thomas Krieger


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Question about final field semantic in case of a race

Aleksey Shipilev-3
On 08/31/2017 11:17 AM, Thomas Krieger wrote:

> I am running the following JCStressTest on a Raspberry Pi 3 with a Java(TM) SE Runtime Environment
> (build 1.8.0_65-b17) Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode):
>
> @JCStressTest
> @Outcome(id = "0", expect = Expect.ACCEPTABLE, desc = "Default outcome.")
> @State
> public class BigDecimalToString {
>     private final  BigDecimal testBigDecimal = new BigDecimal("0.56");
>     @Actor
>     public void actor1(IntResult1 r) {
>         testBigDecimal.toString().length();
>     }
>     @Actor
>     public void actor2(IntResult1 r) {
>         testBigDecimal.toString().length();
>     }    
> }
>
> In about half of the iterations, I see the following Exception:> java.lang.NullPointerException
...

> Or, because of the final field, all threads should have only seen an
> initialized value?

String is published by race, but String.value is final, so it should be safe. Seeing NPE on
dereferencing String.value is weird, and probably points to a compiler bug. Run with more modern
JDK?. It is also not clear if you run ARMv7 or AArch64 VM (not all RPi 3 distros are 64-bit, and
many identify RPi 3 as 32-bit ARM).

Thanks,
-Aleksey



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Question about final field semantic in case of a race

Aleksey Shipilev-3
On 08/31/2017 11:40 AM, Aleksey Shipilev wrote:
> String is published by race, but String.value is final, so it should be safe. Seeing NPE on
> dereferencing String.value is weird, and probably points to a compiler bug. Run with more modern
> JDK?. It is also not clear if you run ARMv7 or AArch64 VM (not all RPi 3 distros are 64-bit, and
> many identify RPi 3 as 32-bit ARM).

Pushed the variants of the test to jcstress, so they are picked up by vendor testing:
  http://hg.openjdk.java.net/code-tools/jcstress/rev/12d706400981

For sanity, booted up my RPi 3 with AArch64 distro, downloaded the AdoptOpenJDK build from here:
  https://github.com/AdoptOpenJDK/openjdk8-releases/releases/tag/jdk8u144-b01

And ran without failures:
 $ j2sdk-image/bin/java -jar jcstress.jar -t strings.Big

*** INTERESTING tests
  Some interesting behaviors observed. This is for the plain curiosity.

  0 matching test results.

*** FAILED tests
  Strong asserts were violated. Correct implementations should have no assert failures here.

  0 matching test results.

*** ERROR tests
  Tests break for some reason, other than failing the assert. Correct implementations should have none.

  0 matching test results.

*** All remaining tests
  Tests that do not fall into any of the previous categories.

  16 matching test results.  Use -v to print them.


Thanks,
-Aleksey



_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Question about final field semantic in case of a race

Thomas Krieger
In reply to this post by Aleksey Shipilev-3

It is ARMv7: uname -a

Linux raspberrypi 4.4.11-v7+ #888 SMP Mon May 23 20:10:33 BST 2016 armv7l GNU/Linux

The JVM is rather new:

java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode)

It is an Oracle JVM (jdk-8-oracle-arm32-vfp-hflt)


Thanks,

Thomas Krieger


On 31 August 2017 at 11:40 Aleksey Shipilev <[hidden email]> wrote:

On 08/31/2017 11:17 AM, Thomas Krieger wrote:

I am running the following JCStressTest on a Raspberry Pi 3 with a Java(TM) SE Runtime Environment
(build 1.8.0_65-b17) Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode):

@JCStressTest
@Outcome(id = "0", expect = Expect.ACCEPTABLE, desc = "Default outcome.")
@State
public class BigDecimalToString {
private final BigDecimal testBigDecimal = new BigDecimal("0.56");
@Actor
public void actor1(IntResult1 r) {
testBigDecimal.toString().length();
}
@Actor
public void actor2(IntResult1 r) {
testBigDecimal.toString().length();
}
}

In about half of the iterations, I see the following Exception:> java.lang.NullPointerException

...

Or, because of the final field, all threads should have only seen an
initialized value?

String is published by race, but String.value is final, so it should be safe. Seeing NPE on
dereferencing String.value is weird, and probably points to a compiler bug. Run with more modern
JDK?. It is also not clear if you run ARMv7 or AArch64 VM (not all RPi 3 distros are 64-bit, and
many identify RPi 3 as 32-bit ARM).

Thanks,
-Aleksey


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: Question about final field semantic in case of a race

Andrew Haley
On 31/08/17 11:20, Thomas Krieger wrote:

> It is ARMv7: uname -a
>
> Linux raspberrypi 4.4.11-v7+ #888 SMP Mon May 23 20:10:33 BST 2016 armv7l GNU/Linux
>
> The JVM is rather new:
>
> java version "1.8.0_65"
> Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
> Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode)
>
> It is an Oracle JVM (jdk-8-oracle-arm32-vfp-hflt)

I think that's a compiler bug.  I haven't got an armv7 system here I can try.
It'd be interesting to see if we can duplicate that with OpenJDK 9.

--
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671
_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest