1 /*
 2  * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
 3  * Copyright (c) 2019 Google and/or its affiliates. All rights reserved.
 4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 5  *
 6  * This code is free software; you can redistribute it and/or modify it
 7  * under the terms of the GNU General Public License version 2 only, as
 8  * published by the Free Software Foundation.
 9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /* @test NonRacyGarbageCollectionLoopTest
26  * @summary Test that objects are tracked correctly when garbage collection happens.
27  * @library /test/lib
28  * @requires vm.gc == null
29  * @build AbstractLoop TsanRunner
30  * @run main/othervm -XX:+UseParallelGC NonRacyGarbageCollectionLoopTest
31  * @run main/othervm -XX:+UseG1GC NonRacyGarbageCollectionLoopTest
32  * @run main/othervm -XX:+UseSerialGC NonRacyGarbageCollectionLoopTest
33  */
34 
35 import java.io.IOException;
36 import jdk.test.lib.process.OutputAnalyzer;
37 import jdk.test.lib.process.ProcessTools;
38 
39 public class NonRacyGarbageCollectionLoopTest {
40   public static void main(String[] args) throws IOException {
41     TsanRunner.runTsanTestExpectSuccess(NonRacyGarbageCollectionLoopRunner.class, "-Xms40m", "-Xmx40m");
42   }
43 }
44 
45 class NonRacyGarbageCollectionLoopRunner extends AbstractLoop {
46   private static final int MEG = 1024 * 1024;
47   // NOTE: If HEAP_SIZE changes, make sure also change -Xms and -Xmx values above.
48   private static final int HEAP_SIZE = 40 * MEG;
49   // Allocate byte arrays that sum up to about 4 times of heap size,
50   // assuming 2 threads and each allocates AbstractLoop.LOOPS times.
51   // Thus garbage collection must have happened and the same address
52   // will be reused to allocate a new object.
53   private static final int BYTE_ARRAY_LENGTH = HEAP_SIZE * 4 / 2 / AbstractLoop.LOOPS;
54 
55   private volatile byte[] array;
56 
57   @Override
58   protected void run(int i) {
59     byte[] arr = new byte[BYTE_ARRAY_LENGTH];
60     for (int j = 0; j < BYTE_ARRAY_LENGTH; j++) {
61       arr[j] = 42;
62     }
63     array = arr;
64   }
65 
66   public static void main(String[] args) throws InterruptedException {
67     NonRacyGarbageCollectionLoopRunner loop = new NonRacyGarbageCollectionLoopRunner();
68     loop.runInTwoThreads();
69     System.out.println("array[0] = " + loop.array[0]);
70   }
71 }