1 /* 2 * Copyright (c) 2012, 2013, 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 /* 25 * @test Test8004741.java 26 * @bug 8004741 27 * @summary Missing compiled exception handle table entry for multidimensional array allocation 28 * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers -XX:+SafepointALot -XX:GuaranteedSafepointInterval=100 Test8004741 29 * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741 30 */ 31 32 import java.util.*; 33 34 public class Test8004741 extends Thread { 35 36 static int passed = 0; 37 38 /** 39 * Loop forever allocating 2-d arrays. 40 * Catches and rethrows all exceptions; in the case of ThreadDeath, increments passed. 41 * Note that passed is incremented here because this is the exception handler with 42 * the smallest scope; we only want to declare success in the case where it is highly 43 * likely that the test condition 44 * (exception in 2-d array alloc interrupted by ThreadDeath) 45 * actually occurs. 46 */ 47 static int[][] test(int a, int b) throws Exception { 48 int[][] ar; 49 try { 50 ar = new int[a][b]; 51 } catch (ThreadDeath e) { 52 System.out.println("test got ThreadDeath"); 53 passed++; 54 throw(e); 55 } 56 return ar; 57 } 58 59 /* Cookbook wait-notify to track progress of test thread. */ 60 Object progressLock = new Object(); 61 private static final int NOT_STARTED = 0; 62 private static final int RUNNING = 1; 63 private static final int STOPPING = 2; 64 65 int progressState = NOT_STARTED; 66 67 void toState(int state) { 68 synchronized (progressLock) { 69 progressState = state; 70 progressLock.notify(); 71 } 72 } 73 74 void waitFor(int state) { 75 synchronized (progressLock) { 76 while (progressState < state) { 77 try { 78 progressLock.wait(); 79 } catch (InterruptedException e) { 80 e.printStackTrace(); 81 System.out.println("unexpected InterruptedException"); 82 fail(); 83 } 84 } 85 if (progressState > state) { 86 System.out.println("unexpected test state change, expected " + 87 state + " but saw " + progressState); 88 fail(); 89 } 90 } 91 } 92 93 /** 94 * Loops running test until some sort of an exception or error, 95 * expects to see ThreadDeath. 96 */ 97 public void run() { 98 try { 99 // Print before state change, so that other thread is most likely 100 // to see this thread executing calls to test() in a loop. 101 System.out.println("thread running"); 102 toState(RUNNING); 103 while (true) { 104 // (2,2) (2,10) (2,100) were observed to tickle the bug; 105 test(2, 100); 106 } 107 } catch (ThreadDeath e) { 108 // nothing to say, passing was incremented by the test. 109 } catch (Throwable e) { 110 e.printStackTrace(); 111 System.out.println("unexpected Throwable " + e); 112 fail(); 113 } 114 toState(STOPPING); 115 } 116 117 /** 118 * Runs a single trial of the test in a thread. 119 * No single trial is definitive, since the ThreadDeath 120 * exception might not land in the tested region of code. 121 */ 122 public static void threadTest() throws InterruptedException { 123 Test8004741 t = new Test8004741(); 124 t.start(); 125 t.waitFor(RUNNING); 126 Thread.sleep(100); 127 System.out.println("stopping thread"); 128 t.stop(); 129 t.waitFor(STOPPING); 130 t.join(); 131 } 132 133 public static void main(String[] args) throws Exception { 134 // Warm up "test" 135 // t will never be started. 136 for (int n = 0; n < 11000; n++) { 137 test(2, 100); 138 } 139 140 // Will this sleep help ensure that the compiler is run? 141 Thread.sleep(500); 142 passed = 0; 143 144 try { 145 test(-1, 100); 146 System.out.println("Missing NegativeArraySizeException #1"); 147 fail(); 148 } catch ( java.lang.NegativeArraySizeException e ) { 149 System.out.println("Saw expected NegativeArraySizeException #1"); 150 } 151 152 try { 153 test(100, -1); 154 fail(); 155 System.out.println("Missing NegativeArraySizeException #2"); 156 fail(); 157 } catch ( java.lang.NegativeArraySizeException e ) { 158 System.out.println("Saw expected NegativeArraySizeException #2"); 159 } 160 161 /* Test repetitions. If the test succeeds-mostly, it succeeds, 162 * as long as it does not crash (the outcome if the exception range 163 * table entry for the array allocation is missing). 164 */ 165 int N = 12; 166 for (int n = 0; n < N; n++) { 167 threadTest(); 168 } 169 170 if (passed > N/2) { 171 System.out.println("Saw " + passed + " out of " + N + " possible ThreadDeath hits"); 172 System.out.println("PASSED"); 173 } else { 174 System.out.println("Too few ThreadDeath hits; expected at least " + N/2 + 175 " but saw only " + passed); 176 fail(); 177 } 178 } 179 180 static void fail() { 181 System.out.println("FAILED"); 182 System.exit(97); 183 } 184 };