1 /* 2 * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import jdk.test.lib.process.ProcessTools; 25 import jdk.test.lib.process.OutputAnalyzer; 26 import java.util.*; 27 import java.util.stream.*; 28 29 /* 30 * @test 31 * @bug 8242263 32 * @summary Exercise DiagnoseSyncOnValueBasedClasses diagnostic flag 33 * @library /test/lib 34 * @run driver/timeout=180000 SyncOnValueBasedClassTest 35 */ 36 37 public class SyncOnValueBasedClassTest { 38 static final int LOOP_COUNT = 3000; 39 static final int THREAD_COUNT = 2; 40 static String[] fatalTests[]; 41 static String[] logTests[]; 42 static List<Object> testObjects = new ArrayList<Object>(); 43 44 private static final String[] specificFlags[] = { 45 {"-Xint", "-XX:+UseBiasedLocking"}, 46 {"-Xint", "-XX:-UseBiasedLocking"}, 47 {"-Xcomp", "-XX:TieredStopAtLevel=1", "-XX:+UseBiasedLocking"}, 48 {"-Xcomp", "-XX:TieredStopAtLevel=1", "-XX:-UseBiasedLocking"}, 49 {"-Xcomp", "-XX:-TieredCompilation", "-XX:-UseBiasedLocking"}, 50 {"-Xcomp", "-XX:-TieredCompilation", "-XX:+UseBiasedLocking", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+UseOptoBiasInlining"}, 51 {"-Xcomp", "-XX:-TieredCompilation", "-XX:+UseBiasedLocking", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UseOptoBiasInlining"} 52 }; 53 54 private static void initTestObjects() { 55 testObjects.add(Character.valueOf('H')); 56 testObjects.add(Boolean.valueOf(true)); 57 testObjects.add(Byte.valueOf((byte)0x40)); 58 testObjects.add(Short.valueOf((short)0x4000)); 59 testObjects.add(Integer.valueOf(0x40000000)); 60 testObjects.add(Long.valueOf(0x4000000000000000L)); 61 testObjects.add(Float.valueOf(1.20f)); 62 testObjects.add(Double.valueOf(1.2345)); 63 } 64 65 private static void generateTests() { 66 initTestObjects(); 67 String[] commonFatalTestsFlags = {"-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", "-XX:DiagnoseSyncOnValueBasedClasses=1"}; 68 fatalTests = new String[specificFlags.length * testObjects.size()][]; 69 for (int i = 0; i < specificFlags.length; i++) { 70 for (int j = 0; j < testObjects.size(); j++) { 71 int index = i * testObjects.size() + j; 72 fatalTests[index] = Stream.of(commonFatalTestsFlags, specificFlags[i], new String[] {"SyncOnValueBasedClassTest$FatalTest", Integer.toString(j)}) 73 .flatMap(Stream::of) 74 .toArray(String[]::new); 75 } 76 } 77 String[] commonLogTestsFlags = {"-XX:+UnlockDiagnosticVMOptions", "-XX:DiagnoseSyncOnValueBasedClasses=2"}; 78 logTests = new String[specificFlags.length][]; 79 for (int i = 0; i < specificFlags.length; i++) { 80 logTests[i] = Stream.of(commonLogTestsFlags, specificFlags[i], new String[] {"SyncOnValueBasedClassTest$LogTest"}) 81 .flatMap(Stream::of) 82 .toArray(String[]::new); 83 } 84 } 85 86 public static void main(String[] args) throws Exception { 87 generateTests(); 88 for (int i = 0; i < fatalTests.length; i++) { 89 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(fatalTests[i]); 90 OutputAnalyzer output = ProcessTools.executeProcess(pb); 91 output.shouldContain("fatal error: Synchronizing on object"); 92 output.shouldNotContain("synchronization on value based class did not fail"); 93 output.shouldNotHaveExitValue(0); 94 } 95 for (int i = 0; i < logTests.length; i++) { 96 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(logTests[i]); 97 OutputAnalyzer output = ProcessTools.executeProcess(pb); 98 output.shouldHaveExitValue(0); 99 checkOutput(output); 100 } 101 } 102 103 private static void checkOutput(OutputAnalyzer output) { 104 String out = output.getOutput(); 105 assertTrue(out.matches("(?s).*Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Character.*")); 106 assertTrue(out.matches("(?s).*Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Boolean.*")); 107 assertTrue(out.matches("(?s).*Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Byte.*")); 108 assertTrue(out.matches("(?s).*Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Short.*")); 109 assertTrue(out.matches("(?s).*Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Integer.*")); 110 assertTrue(out.matches("(?s).*Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Long.*")); 111 String[] res = out.split("Synchronizing on object 0[xX][0-9a-fA-F]+ of klass java\\.lang\\.Float\\R"); 112 assertTrue(res.length - 1 == (LOOP_COUNT * THREAD_COUNT + 1), res.length - 1); 113 } 114 115 private static void assertTrue(boolean condition) { 116 if (!condition) { 117 throw new RuntimeException("No synchronization matches"); 118 } 119 } 120 121 private static void assertTrue(boolean condition, int count) { 122 if (!condition) { 123 throw new RuntimeException("Synchronization count was " + count); 124 } 125 } 126 127 static class FatalTest { 128 public static void main(String[] args) throws Exception { 129 initTestObjects(); 130 synchronized (testObjects.get(Integer.valueOf(args[0]))) { 131 throw new RuntimeException("synchronization on value based class did not fail"); 132 } 133 } 134 } 135 136 static class LogTest implements Runnable { 137 private static long sharedCounter = 0L; 138 private static Float sharedLock1 = 0.0f; 139 140 public static void main(String[] args) throws Exception { 141 initTestObjects(); 142 for (Object obj : testObjects) { 143 synchronized (obj) { 144 sharedCounter++; 145 } 146 } 147 148 LogTest test = new LogTest(); 149 Thread[] threads = new Thread[THREAD_COUNT]; 150 for (int i = 0; i < threads.length; i++) { 151 threads[i] = new Thread(test); 152 threads[i].start(); 153 } 154 for (Thread t : threads) { 155 t.join(); 156 } 157 } 158 159 @Override 160 public void run() { 161 for (int i = 0; i < LOOP_COUNT; i++) { 162 synchronized (sharedLock1) { 163 sharedCounter++; 164 } 165 } 166 } 167 } 168 }