changeset 279:f1b557c22a53

Chapter 1.a: VarHandles basic tests.
author shade
date Tue, 31 May 2016 19:25:26 +0300
parents b0d5180fe14b
children 5e67118d550e
files jcstress-core/src/main/java/org/openjdk/jcstress/util/StringUtils.java jcstress-test-gen/pom.xml jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter0aTestGenerator.java jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter1aTestGenerator.java jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/GeneratorUtils.java jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleArrayAtomicityTest.java.template jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleByteArrayViewAtomicityTest.java.template jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleDirectByteBufferViewAtomicityTest.java.template jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleFieldAtomicityTest.java.template jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleHeapByteBufferViewAtomicityTest.java.template tests-chapter-1a/pom.xml
diffstat 11 files changed, 668 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/util/StringUtils.java	Mon May 30 20:09:20 2016 +0300
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/util/StringUtils.java	Tue May 31 19:25:26 2016 +0300
@@ -78,4 +78,8 @@
         return name.replace("org.openjdk.jcstress.tests", "o.o.j.t");
     }
 
+    public static String upcaseFirst(String s) {
+        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
+    }
+
 }
--- a/jcstress-test-gen/pom.xml	Mon May 30 20:09:20 2016 +0300
+++ b/jcstress-test-gen/pom.xml	Tue May 31 19:25:26 2016 +0300
@@ -122,6 +122,22 @@
                             </transformers>
                         </configuration>
                     </execution>
+                    <execution>
+                        <id>chapter1a-generator</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <finalName>chapter1a-generator</finalName>
+                            <transformers>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.openjdk.jcstress.chapters.Chapter1aTestGenerator</mainClass>
+                                </transformer>
+                            </transformers>
+                        </configuration>
+                    </execution>
                 </executions>
             </plugin>
             <plugin>
--- a/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter0aTestGenerator.java	Mon May 30 20:09:20 2016 +0300
+++ b/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter0aTestGenerator.java	Tue May 31 19:25:26 2016 +0300
@@ -26,14 +26,10 @@
 
 import org.openjdk.jcstress.Spp;
 import org.openjdk.jcstress.Values;
+import org.openjdk.jcstress.util.StringUtils;
 
 import java.io.*;
-import java.nio.charset.Charset;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.*;
-import java.util.stream.Collectors;
 
 public class Chapter0aTestGenerator {
 
@@ -48,84 +44,84 @@
 
         makeTests(
                 dest,
-                readFromResource("/accessAtomic/X-FieldAtomicityTest.java.template"),
+                GeneratorUtils.readFromResource("/accessAtomic/X-FieldAtomicityTest.java.template"),
                 "accessAtomic.fields",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/defaultValues/X-FieldDefaultValuesTest.java.template"),
+                GeneratorUtils.readFromResource("/defaultValues/X-FieldDefaultValuesTest.java.template"),
                 "defaultValues.fields",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/init/X-FieldInitTest.java.template"),
+                GeneratorUtils.readFromResource("/init/X-FieldInitTest.java.template"),
                 "init.fields",
                 new String[]{ "", "volatile", "final" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/tearing/X-FieldTearingTest.java.template"),
+                GeneratorUtils.readFromResource("/tearing/X-FieldTearingTest.java.template"),
                 "tearing.fields",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/defaultValues/X-ArrayDefaultValuesTest.java.template"),
+                GeneratorUtils.readFromResource("/defaultValues/X-ArrayDefaultValuesTest.java.template"),
                 "defaultValues.arrays.small",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/defaultValues/X-ArrayLargeDefaultValuesTest.java.template"),
+                GeneratorUtils.readFromResource("/defaultValues/X-ArrayLargeDefaultValuesTest.java.template"),
                 "defaultValues.arrays.large",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/init/X-ArrayInitTest.java.template"),
+                GeneratorUtils.readFromResource("/init/X-ArrayInitTest.java.template"),
                 "init.arrays.small",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/init/X-ArrayLargeInitTest.java.template"),
+                GeneratorUtils.readFromResource("/init/X-ArrayLargeInitTest.java.template"),
                 "init.arrays.large",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/accessAtomic/X-ArrayAtomicityTest.java.template"),
+                GeneratorUtils.readFromResource("/accessAtomic/X-ArrayAtomicityTest.java.template"),
                 "accessAtomic.arrays.small",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/accessAtomic/X-ArrayLargeAtomicityTest.java.template"),
+                GeneratorUtils.readFromResource("/accessAtomic/X-ArrayLargeAtomicityTest.java.template"),
                 "accessAtomic.arrays.large",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/tearing/X-ArrayTearingTest.java.template"),
+                GeneratorUtils.readFromResource("/tearing/X-ArrayTearingTest.java.template"),
                 "tearing.arrays.small",
                 new String[]{ "", "volatile" }
         );
 
         makeTests(
                 dest,
-                readFromResource("/tearing/X-ArrayLargeTearingTest.java.template"),
+                GeneratorUtils.readFromResource("/tearing/X-ArrayLargeTearingTest.java.template"),
                 "tearing.arrays.large",
                 new String[]{ "", "volatile" }
         );
@@ -140,20 +136,17 @@
                         keys(modifier, type),
                         vars(modifier, type, pack, name));
 
-                writeOut(dest, pack, name, res);
+                GeneratorUtils.writeOut(dest, pack, name, res);
             }
         }
     }
 
-    private static String upcaseFirst(String s) {
-        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
-    }
 
     private static Map<String, String> vars(String modifier, String type, String pack, String name) {
         Map<String, String> map = new HashMap<>();
         map.put("type", type);
         map.put("TYPE", type.toUpperCase());
-        map.put("Type", upcaseFirst(type));
+        map.put("Type", StringUtils.upcaseFirst(type));
         map.put("name", name);
         map.put("default", Values.DEFAULTS.get(type));
         map.put("defaultLiteral", Values.DEFAULTS_LITERAL.get(type));
@@ -179,44 +172,7 @@
     }
 
     private static String testName(String type) {
-        return upcaseFirst(type) + "Test";
-    }
-
-    private static void writeOut(String destination, String pkg, String name, String contents) throws IOException {
-        Path dir = Paths.get(destination, pkg.replaceAll("\\.", File.separator));
-        Path file = Paths.get(destination, pkg.replaceAll("\\.", File.separator), name + ".java");
-        Files.createDirectories(dir);
-
-        boolean doWrite = true;
-        try {
-            List<String> l = Files.readAllLines(file);
-            String exists = l.stream().collect(Collectors.joining(System.lineSeparator()));
-            if (contents.equals(exists)) {
-                doWrite = false;
-            }
-        } catch (IOException e) {
-            // Moving on...
-        }
-
-        if (doWrite) {
-            System.out.println("Generating: " + file);
-            Files.write(file, Arrays.asList(contents), Charset.defaultCharset());
-        } else {
-            System.out.println("Skip, no modifications: " + file);
-        }
-    }
-
-    private static String readFromResource(String name) throws IOException {
-        InputStream is = Chapter0aTestGenerator.class.getResourceAsStream(name);
-        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
-
-        StringBuilder sb = new StringBuilder();
-        String l;
-        while ((l = reader.readLine()) != null) {
-            sb.append(l);
-            sb.append(System.lineSeparator());
-        }
-        return sb.toString();
+        return StringUtils.upcaseFirst(type) + "Test";
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/Chapter1aTestGenerator.java	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jcstress.chapters;
+
+import org.openjdk.jcstress.Spp;
+import org.openjdk.jcstress.Values;
+import org.openjdk.jcstress.util.StringUtils;
+
+import java.io.*;
+import java.nio.ByteOrder;
+import java.util.*;
+
+public class Chapter1aTestGenerator {
+
+    public static final String PREFIX = "org.openjdk.jcstress.tests";
+    public static final String[] TYPES_ALL = new String[]{"byte", "boolean", "char", "short", "int", "float", "long", "double", "String"};
+    public static final String[] TYPES_VIEWS = new String[]{"char", "short", "int", "float", "long", "double"};
+
+    public static void main(String... args) throws IOException {
+        if (args.length < 1) {
+            throw new IllegalStateException("Need a destination argument");
+        }
+        String dest = args[0];
+
+        makeTests(
+                dest,
+                GeneratorUtils.readFromResource("/accessAtomic/X-VarHandleFieldAtomicityTest.java.template"),
+                "accessAtomic.varHandles.fields"
+        );
+
+        makeTests(
+                dest,
+                GeneratorUtils.readFromResource("/accessAtomic/X-VarHandleArrayAtomicityTest.java.template"),
+                "accessAtomic.varHandles.arrays"
+        );
+
+        makeBufferTests(
+                dest,
+                GeneratorUtils.readFromResource("/accessAtomic/X-VarHandleByteArrayViewAtomicityTest.java.template"),
+                "accessAtomic.varHandles.byteArray"
+        );
+
+        makeBufferTests(
+                dest,
+                GeneratorUtils.readFromResource("/accessAtomic/X-VarHandleHeapByteBufferViewAtomicityTest.java.template"),
+                "accessAtomic.varHandles.byteBuffer.heap"
+        );
+
+        makeBufferTests(
+                dest,
+                GeneratorUtils.readFromResource("/accessAtomic/X-VarHandleDirectByteBufferViewAtomicityTest.java.template"),
+                "accessAtomic.varHandles.byteBuffer.direct"
+        );
+    }
+
+    private enum VarHandleMode {
+        NAKED("plain"),
+        OPAQUE("opaque"),
+        ACQ_REL("acqrel"),
+        VOLATILE("volatiles"),
+        ;
+
+        private String label;
+
+        VarHandleMode(String label) {
+            this.label = label;
+        }
+
+        @Override
+        public String toString() {
+            return label;
+        }
+    }
+
+    private static void makeTests(String dest, String template, String label) throws IOException {
+        for (VarHandleMode gs : VarHandleMode.values()) {
+            String pack = PREFIX + "." + label + "." + gs;
+            for (String type : TYPES_ALL) {
+                String name = testName(type);
+                String res = Spp.spp(template,
+                        keys(type, gs),
+                        vars(type, pack, name, gs, null));
+
+                GeneratorUtils.writeOut(dest, pack, name, res);
+            }
+        }
+    }
+
+    private static void makeBufferTests(String dest, String template, String label) throws IOException {
+        for (VarHandleMode gs : VarHandleMode.values()) {
+            for (ByteOrder bo : new ByteOrder[] { ByteOrder.BIG_ENDIAN, ByteOrder.LITTLE_ENDIAN }) {
+                String pack = PREFIX + "." + label + "." + bo.toString().toLowerCase().replace("_endian", "") + "." + gs;
+                for (String type : TYPES_VIEWS) {
+                    String name = testName(type);
+                    String res = Spp.spp(template,
+                            keys(type, gs),
+                            vars(type, pack, name, gs, bo));
+
+                    GeneratorUtils.writeOut(dest, pack, name, res);
+                }
+            }
+        }
+    }
+
+    private static Map<String, String> vars(String type, String pack, String name, VarHandleMode mode, ByteOrder bo) {
+        Map<String, String> map = new HashMap<>();
+        map.put("type", type);
+        map.put("TYPE", type.toUpperCase());
+        map.put("Type", StringUtils.upcaseFirst(type));
+        map.put("name", name);
+        map.put("default", Values.DEFAULTS.get(type));
+        map.put("defaultLiteral", Values.DEFAULTS_LITERAL.get(type));
+        map.put("set", Values.VALUES.get(type));
+        map.put("setLiteral", Values.VALUES_LITERAL.get(type));
+        map.put("package", pack);
+        map.put("byteOrder", String.valueOf(bo));
+
+        switch (mode) {
+            case NAKED: {
+                map.put("setOp", "set");
+                map.put("getOp", "get");
+                break;
+            }
+            case OPAQUE: {
+                map.put("setOp", "setOpaque");
+                map.put("getOp", "getOpaque");
+                break;
+            }
+            case ACQ_REL: {
+                map.put("setOp", "setRelease");
+                map.put("getOp", "getAcquire");
+                break;
+            }
+            case VOLATILE: {
+                map.put("setOp", "setVolatile");
+                map.put("getOp", "getVolatile");
+                break;
+            }
+            default:
+                throw new IllegalStateException("" + mode);
+        }
+        return map;
+    }
+
+    private static Set<String> keys(String type, VarHandleMode mode) {
+        Set<String> set = new HashSet<>();
+        set.add(type);
+        if (alwaysAtomic(type, mode)) {
+            set.add("alwaysAtomic");
+        }
+        return set;
+    }
+
+    private static boolean alwaysAtomic(String type, VarHandleMode mode) {
+        switch (mode) {
+            case NAKED:
+                return !(type.equals("double") || type.equals("long"));
+            case ACQ_REL:
+            case OPAQUE:
+            case VOLATILE:
+                return true;
+            default:
+                throw new IllegalStateException(mode.toString());
+        }
+    }
+
+    private static String testName(String type) {
+        return StringUtils.upcaseFirst(type) + "Test";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/java/org/openjdk/jcstress/chapters/GeneratorUtils.java	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.openjdk.jcstress.chapters;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class GeneratorUtils {
+    static void writeOut(String destination, String pkg, String name, String contents) throws IOException {
+        Path dir = Paths.get(destination, pkg.replaceAll("\\.", File.separator));
+        Path file = Paths.get(destination, pkg.replaceAll("\\.", File.separator), name + ".java");
+        Files.createDirectories(dir);
+
+        boolean doWrite = true;
+        try {
+            List<String> l = Files.readAllLines(file);
+            String exists = l.stream().collect(Collectors.joining(System.lineSeparator()));
+            if (contents.equals(exists)) {
+                doWrite = false;
+            }
+        } catch (IOException e) {
+            // Moving on...
+        }
+
+        if (doWrite) {
+            System.out.println("Generating: " + file);
+            Files.write(file, Arrays.asList(contents), Charset.defaultCharset());
+        } else {
+            System.out.println("Skip, no modifications: " + file);
+        }
+    }
+
+    static String readFromResource(String name) throws IOException {
+        InputStream is = Chapter0aTestGenerator.class.getResourceAsStream(name);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+
+        StringBuilder sb = new StringBuilder();
+        String l;
+        while ((l = reader.readLine()) != null) {
+            sb.append(l);
+            sb.append(System.lineSeparator());
+        }
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleArrayAtomicityTest.java.template	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package $package$;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+import org.openjdk.jcstress.annotations.*;
+import org.openjdk.jcstress.infra.results.*;
+
+#warn
+
+/**
+ * Tests if fields experience non-atomic reads/writes.
+ */
+@JCStressTest
+@Outcome(id = "[$default$]", expect = Expect.ACCEPTABLE, desc = "Default value for the field. Allowed to see this: data race.")
+@Outcome(id = "[$set$]", expect = Expect.ACCEPTABLE, desc = "The value set by the actor thread. Observer sees the complete update.")
+#if[alwaysAtomic]
+@Outcome(expect = Expect.FORBIDDEN, desc = "Other values are forbidden: atomicity violation.")
+#else[alwaysAtomic]
+@Outcome(expect = Expect.ACCEPTABLE_SPEC, desc = "Non-atomic access detected, allowed by spec")
+@Ref("http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7")
+#end[alwaysAtomic]
+@State
+public class $name$ {
+
+    static final VarHandle VH = MethodHandles.arrayElementVarHandle($type$[].class);
+
+    $type$[] xs = new $type$[1];
+
+    @Actor
+    public void actor1() {
+        VH.$setOp$(xs, 0, $setLiteral$);
+    }
+
+    @Actor
+    public void actor2($Type$Result1 r) {
+        r.r1 = ($type$)VH.$getOp$(xs, 0);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleByteArrayViewAtomicityTest.java.template	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package $package$;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+
+import org.openjdk.jcstress.annotations.*;
+import org.openjdk.jcstress.infra.results.*;
+
+#warn
+
+/**
+ * Tests if fields experience non-atomic reads/writes.
+ */
+@JCStressTest
+@Outcome(id = "[$default$]", expect = Expect.ACCEPTABLE, desc = "Default value for the field. Allowed to see this: data race.")
+@Outcome(id = "[$set$]", expect = Expect.ACCEPTABLE, desc = "The value set by the actor thread. Observer sees the complete update.")
+#if[alwaysAtomic]
+@Outcome(expect = Expect.FORBIDDEN, desc = "Other values are forbidden: atomicity violation.")
+#else[alwaysAtomic]
+@Outcome(expect = Expect.ACCEPTABLE_SPEC, desc = "Non-atomic access detected, allowed by spec")
+@Ref("http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7")
+#end[alwaysAtomic]
+@State
+public class $name$ {
+
+    static final int OFF = ByteBuffer.wrap(new byte[128]).alignmentOffset(0, 8);
+    static final VarHandle VH = MethodHandles.byteArrayViewVarHandle($type$[].class, ByteOrder.$byteOrder$);
+
+    byte[] xs = new byte[OFF + 8];
+
+    @Actor
+    public void actor1() {
+        VH.$setOp$(xs, OFF, $setLiteral$);
+    }
+
+    @Actor
+    public void actor2($Type$Result1 r) {
+        r.r1 = ($type$)VH.$getOp$(xs, OFF);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleDirectByteBufferViewAtomicityTest.java.template	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package $package$;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+
+import org.openjdk.jcstress.annotations.*;
+import org.openjdk.jcstress.infra.results.*;
+
+#warn
+
+/**
+ * Tests if fields experience non-atomic reads/writes.
+ */
+@JCStressTest
+@Outcome(id = "[$default$]", expect = Expect.ACCEPTABLE, desc = "Default value for the field. Allowed to see this: data race.")
+@Outcome(id = "[$set$]", expect = Expect.ACCEPTABLE, desc = "The value set by the actor thread. Observer sees the complete update.")
+#if[alwaysAtomic]
+@Outcome(expect = Expect.FORBIDDEN, desc = "Other values are forbidden: atomicity violation.")
+#else[alwaysAtomic]
+@Outcome(expect = Expect.ACCEPTABLE_SPEC, desc = "Non-atomic access detected, allowed by spec")
+@Ref("http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7")
+#end[alwaysAtomic]
+@State
+public class $name$ {
+
+    static final VarHandle VH = MethodHandles.byteBufferViewVarHandle($type$[].class, ByteOrder.$byteOrder$);
+
+    ByteBuffer buf = ByteBuffer.allocateDirect(16);
+    int off = buf.alignmentOffset(0, 8);
+
+    @Actor
+    public void actor1() {
+        VH.$setOp$(buf, off, $setLiteral$);
+    }
+
+    @Actor
+    public void actor2($Type$Result1 r) {
+        r.r1 = ($type$)VH.$getOp$(buf, off);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleFieldAtomicityTest.java.template	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package $package$;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+import org.openjdk.jcstress.annotations.*;
+import org.openjdk.jcstress.infra.results.*;
+
+#warn
+
+/**
+ * Tests if fields experience non-atomic reads/writes.
+ */
+@JCStressTest
+@Outcome(id = "[$default$]", expect = Expect.ACCEPTABLE, desc = "Default value for the field. Allowed to see this: data race.")
+@Outcome(id = "[$set$]", expect = Expect.ACCEPTABLE, desc = "The value set by the actor thread. Observer sees the complete update.")
+#if[alwaysAtomic]
+@Outcome(expect = Expect.FORBIDDEN, desc = "Other values are forbidden: atomicity violation.")
+#else[alwaysAtomic]
+@Outcome(expect = Expect.ACCEPTABLE_SPEC, desc = "Non-atomic access detected, allowed by spec")
+@Ref("http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7")
+#end[alwaysAtomic]
+@State
+public class $name$ {
+
+    $type$ x;
+
+    static final VarHandle VH;
+
+    static {
+        try {
+            VH = MethodHandles.lookup().findVarHandle($name$.class, "x", $type$.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Actor
+    public void actor1() {
+        VH.$setOp$(this, $setLiteral$);
+    }
+
+    @Actor
+    public void actor2($Type$Result1 r) {
+        r.r1 = ($type$)VH.$getOp$(this);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jcstress-test-gen/src/main/resources/accessAtomic/X-VarHandleHeapByteBufferViewAtomicityTest.java.template	Tue May 31 19:25:26 2016 +0300
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package $package$;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.nio.ByteOrder;
+import java.nio.ByteBuffer;
+
+import org.openjdk.jcstress.annotations.*;
+import org.openjdk.jcstress.infra.results.*;
+
+#warn
+
+/**
+ * Tests if fields experience non-atomic reads/writes.
+ */
+@JCStressTest
+@Outcome(id = "[$default$]", expect = Expect.ACCEPTABLE, desc = "Default value for the field. Allowed to see this: data race.")
+@Outcome(id = "[$set$]", expect = Expect.ACCEPTABLE, desc = "The value set by the actor thread. Observer sees the complete update.")
+#if[alwaysAtomic]
+@Outcome(expect = Expect.FORBIDDEN, desc = "Other values are forbidden: atomicity violation.")
+#else[alwaysAtomic]
+@Outcome(expect = Expect.ACCEPTABLE_SPEC, desc = "Non-atomic access detected, allowed by spec")
+@Ref("http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7")
+#end[alwaysAtomic]
+@State
+public class $name$ {
+
+    static final VarHandle VH = MethodHandles.byteBufferViewVarHandle($type$[].class, ByteOrder.$byteOrder$);
+
+    ByteBuffer buf = ByteBuffer.allocate(16);
+    int off = buf.alignmentOffset(0, 8);
+
+    @Actor
+    public void actor1() {
+        VH.$setOp$(buf, off, $setLiteral$);
+    }
+
+    @Actor
+    public void actor2($Type$Result1 r) {
+        r.r1 = ($type$)VH.$getOp$(buf, off);
+    }
+
+}
+
--- a/tests-chapter-1a/pom.xml	Mon May 30 20:09:20 2016 +0300
+++ b/tests-chapter-1a/pom.xml	Tue May 31 19:25:26 2016 +0300
@@ -69,6 +69,30 @@
             </plugin>
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <version>1.2.1</version>
+                <executions>
+                    <execution>
+                        <id>chapter1a-gen</id>
+                        <goals>
+                            <goal>exec</goal>
+                        </goals>
+                        <phase>
+                            generate-sources
+                        </phase>
+                        <configuration>
+                            <executable>${java.home}/bin/java</executable>
+                            <arguments>
+                                <argument>-jar</argument>
+                                <argument>../jcstress-test-gen/target/chapter1a-generator.jar</argument>
+                                <argument>${project.build.sourceDirectory}/</argument>
+                            </arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
                 <version>1.7</version>
                 <executions>