1 package shared; 2 3 import java.lang.management.ManagementFactory; 4 import java.lang.management.OperatingSystemMXBean; 5 import java.util.Arrays; 6 //import com.sun.management.OperatingSystemMXBean; 7 import java.util.concurrent.atomic.AtomicBoolean; 8 import java.util.concurrent.atomic.AtomicIntegerArray; 9 10 /** 11 * Monitors CPU utilization to determine if the program has crashed. 12 * Also performs VM forced shutdowns and safe memory allocation. 13 * @author Brian Bushnell 14 * @date Feb 25, 2015 15 * 16 */ 17 public final class KillSwitch extends Thread { 18 main(String[] args)19 public static void main(String[] args){ 20 double seconds=Double.parseDouble(args[0]); 21 double load=Double.parseDouble(args[1]); 22 launch(seconds, load); 23 if(args.length>2){ 24 25 } 26 } 27 KillSwitch(double seconds, double load)28 private KillSwitch(double seconds, double load) { 29 maxSeconds=seconds; 30 minLoad=load; 31 } 32 launch()33 public static boolean launch(){ 34 return launch(600); 35 } 36 launch(double seconds)37 public static boolean launch(double seconds){ 38 return launch(seconds, 0.002); 39 } 40 launch(double seconds, double load)41 public static synchronized boolean launch(double seconds, double load){ 42 if(count>0){return false;} 43 ks=new KillSwitch(seconds, load); 44 ks.start(); 45 return true; 46 } 47 48 @Override run()49 public void run(){ 50 51 boolean success=monitor(); 52 // System.err.println("success: "+success); 53 if(!success || killFlag.get()){ 54 if(!suppressMessages){ 55 System.err.println("Process has decided it has crashed, and will abort.\n" + 56 "If this decision was incorrect, please re-run with the flag 'monitor=f'"); 57 } 58 kill0(); 59 } 60 } 61 monitor()62 private boolean monitor(){ 63 64 final OperatingSystemMXBean bean=ManagementFactory.getOperatingSystemMXBean(); 65 if(bean.getSystemLoadAverage()<0){ 66 System.err.println("This OS does not support monitor, so monitoring was disabled."); 67 return true; 68 } 69 70 final long start=System.currentTimeMillis(); 71 final long buffer=(long)(1+maxSeconds*1000); 72 long stop=start+buffer; 73 // System.err.println("start="+start+", stop="+stop+", buffer="+buffer); 74 // System.err.println("shutdownFlag.get()="+shutdownFlag.get()); 75 while(!shutdownFlag.get()){ 76 try { 77 sleep(500); 78 } catch (InterruptedException e) { 79 // TODO Auto-generated catch block 80 e.printStackTrace(); 81 } 82 final double load=bean.getSystemLoadAverage(); 83 final long time=System.currentTimeMillis(); 84 if(load>minLoad){stop=time+buffer;} 85 if(time>stop){return false;} 86 // System.err.println("stop-time="+(stop-time)+", load="+load); 87 } 88 // System.err.println("shutdownFlag.get()="+shutdownFlag.get()); 89 return true; 90 } 91 92 /*--------------------------------------------------------------*/ 93 kill(String s)94 public static synchronized void kill(String s){ 95 ballast=null; 96 Exception e=new Exception(s); 97 e.printStackTrace(); 98 kill0(); 99 } 100 101 // public static void kill(Throwable e){ 102 // e.printStackTrace(); 103 // kill0(); 104 // } 105 kill()106 public static synchronized void kill(){ 107 ballast=null; 108 Exception e=new Exception("Aborting."); 109 e.printStackTrace(); 110 kill0(); 111 } 112 killSilent()113 public static synchronized void killSilent(){ 114 ballast=null; 115 kill0(); 116 } 117 kill0()118 private static void kill0(){ 119 ballast=null; 120 Runtime.getRuntime().halt(1); 121 } 122 shutdown()123 public static void shutdown(){ 124 shutdownFlag.set(true); 125 } 126 setKillFlag()127 public static void setKillFlag(){ 128 killFlag.set(true); 129 } 130 131 /*--------------------------------------------------------------*/ 132 throwableKill(Throwable e)133 public static final void throwableKill(Throwable e){ 134 ballast=null; 135 synchronized(MemKillMessage){ 136 e.printStackTrace(); 137 kill0(); 138 } 139 } 140 exceptionKill(Exception e)141 public static final void exceptionKill(Exception e){ 142 ballast=null; 143 synchronized(MemKillMessage){ 144 e.printStackTrace(); 145 kill0(); 146 } 147 } 148 memKill(OutOfMemoryError e)149 public static final void memKill(OutOfMemoryError e){ 150 ballast=null; 151 synchronized(MemKillMessage){ 152 e.printStackTrace(); 153 System.err.println(MemKillMessage); 154 // Shared.printMemory(); 155 // killSilent(); 156 kill0(); 157 } 158 } 159 assertionKill(AssertionError e)160 public static final void assertionKill(AssertionError e){ 161 ballast=null; 162 synchronized(MemKillMessage){ 163 // System.err.println(e); 164 e.printStackTrace(); 165 kill0(); 166 } 167 } 168 169 170 /*--------------------------------------------------------------*/ 171 allocAtomicInt(int len)172 public static final AtomicIntegerArray allocAtomicInt(int len){ 173 AtomicIntegerArray ret=null; 174 try { 175 ret=new AtomicIntegerArray(len); 176 } catch (OutOfMemoryError e) { 177 memKill(e); 178 } 179 return ret; 180 } 181 allocLong1D(int len)182 public static final long[] allocLong1D(int len){ 183 long[] ret=null; 184 try { 185 ret=new long[len]; 186 } catch (OutOfMemoryError e) { 187 memKill(e); 188 } 189 return ret; 190 } 191 allocInt1D(int len)192 public static final int[] allocInt1D(int len){ 193 int[] ret=null; 194 try { 195 ret=new int[len]; 196 } catch (OutOfMemoryError e) { 197 memKill(e); 198 } 199 return ret; 200 } 201 allocFloat1D(int len)202 public static float[] allocFloat1D(int len) { 203 float[] ret=null; 204 try { 205 ret=new float[len]; 206 } catch (OutOfMemoryError e) { 207 memKill(e); 208 } 209 return ret; 210 } 211 allocDouble1D(int len)212 public static double[] allocDouble1D(int len) { 213 double[] ret=null; 214 try { 215 ret=new double[len]; 216 } catch (OutOfMemoryError e) { 217 memKill(e); 218 } 219 return ret; 220 } 221 allocByte1D(int len)222 public static final byte[] allocByte1D(int len){ 223 byte[] ret=null; 224 try { 225 ret=new byte[len]; 226 } catch (OutOfMemoryError e) { 227 memKill(e); 228 } 229 return ret; 230 } 231 allocChar1D(int len)232 public static final char[] allocChar1D(int len){ 233 char[] ret=null; 234 try { 235 ret=new char[len]; 236 } catch (OutOfMemoryError e) { 237 memKill(e); 238 } 239 return ret; 240 } 241 242 /*--------------------------------------------------------------*/ 243 allocInt2D(int x)244 public static final int[][] allocInt2D(int x){ 245 int[][] ret=null; 246 try { 247 ret=new int[x][]; 248 } catch (OutOfMemoryError e) { 249 memKill(e); 250 } 251 return ret; 252 } 253 allocInt2D(int x, int y)254 public static final int[][] allocInt2D(int x, int y){ 255 int[][] ret=null; 256 try { 257 ret=new int[x][y]; 258 } catch (OutOfMemoryError e) { 259 ballast2=null; 260 System.err.print(x+","+y); 261 memKill(e); 262 } 263 return ret; 264 } 265 allocFloat2D(int x)266 public static final float[][] allocFloat2D(int x){ 267 float[][] ret=null; 268 try { 269 ret=new float[x][]; 270 } catch (OutOfMemoryError e) { 271 memKill(e); 272 } 273 return ret; 274 } 275 allocFloat2D(int x, int y)276 public static final float[][] allocFloat2D(int x, int y){ 277 float[][] ret=null; 278 try { 279 ret=new float[x][y]; 280 } catch (OutOfMemoryError e) { 281 ballast2=null; 282 System.err.print(x+","+y); 283 memKill(e); 284 } 285 return ret; 286 } 287 allocLong2D(int x)288 public static final long[][] allocLong2D(int x){ 289 long[][] ret=null; 290 try { 291 ret=new long[x][]; 292 } catch (OutOfMemoryError e) { 293 memKill(e); 294 } 295 return ret; 296 } 297 allocLong2D(int x, int y)298 public static final long[][] allocLong2D(int x, int y){ 299 long[][] ret=null; 300 try { 301 ret=new long[x][y]; 302 } catch (OutOfMemoryError e) { 303 memKill(e); 304 } 305 return ret; 306 } 307 308 /*--------------------------------------------------------------*/ 309 allocInt3D(int x)310 public static int[][][] allocInt3D(int x) { 311 int[][][] ret=null; 312 try { 313 ret=new int[x][][]; 314 } catch (OutOfMemoryError e) { 315 memKill(e); 316 } 317 return ret; 318 } 319 allocInt3D(int x, int y)320 public static int[][][] allocInt3D(int x, int y) { 321 int[][][] ret=null; 322 try { 323 ret=new int[x][y][]; 324 } catch (OutOfMemoryError e) { 325 memKill(e); 326 } 327 return ret; 328 } 329 allocInt3D(int x, int y, int z)330 public static int[][][] allocInt3D(int x, int y, int z) { 331 int[][][] ret=null; 332 try { 333 ret=new int[x][y][z]; 334 } catch (OutOfMemoryError e) { 335 memKill(e); 336 } 337 return ret; 338 } 339 340 /*--------------------------------------------------------------*/ 341 copyOf(byte[] buffer, long newLength)342 public static byte[] copyOf(byte[] buffer, long newLength) { 343 final int len=buffer.length; 344 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 345 if(newLength>len2 && len2<=len){ 346 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 347 } 348 byte[] copy=null; 349 try { 350 copy=Arrays.copyOf(buffer, len2); 351 } catch (OutOfMemoryError e) { 352 memKill(e); 353 } 354 return copy; 355 } 356 copyOf(float[] buffer, long newLength)357 public static float[] copyOf(float[] buffer, long newLength) { 358 final int len=buffer.length; 359 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 360 if(newLength>len2 && len2<=len){ 361 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 362 } 363 float[] copy=null; 364 try { 365 copy=Arrays.copyOf(buffer, len2); 366 } catch (OutOfMemoryError e) { 367 memKill(e); 368 } 369 return copy; 370 } 371 copyOf(double[] buffer, long newLength)372 public static double[] copyOf(double[] buffer, long newLength) { 373 final int len=buffer.length; 374 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 375 if(newLength>len2 && len2<=len){ 376 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 377 } 378 double[] copy=null; 379 try { 380 copy=Arrays.copyOf(buffer, len2); 381 } catch (OutOfMemoryError e) { 382 memKill(e); 383 } 384 return copy; 385 } 386 387 /** 388 * Copy the buffer into an array of size newLength. 389 * Fill extra cells with fillValue. 390 * @param buffer Old array 391 * @param newLength Length of new array 392 * @param fillValue Value to insert in extra cells 393 * @return New array 394 */ copyAndFill(int[] buffer, long newLength, int fillValue)395 public static int[] copyAndFill(int[] buffer, long newLength, int fillValue) { 396 final int[] copy=copyOf(buffer, newLength); 397 Arrays.fill(copy, buffer.length, copy.length, fillValue); 398 return copy; 399 } 400 copyOf(int[] buffer, long newLength)401 public static int[] copyOf(int[] buffer, long newLength) { 402 final int len=buffer.length; 403 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 404 if(newLength>len2 && len2<=len){ 405 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 406 } 407 int[] copy=null; 408 try { 409 copy=Arrays.copyOf(buffer, len2); 410 } catch (OutOfMemoryError e) { 411 memKill(e); 412 } 413 return copy; 414 } 415 copyOf(int[][] buffer, long newLength)416 public static int[][] copyOf(int[][] buffer, long newLength) { 417 final int len=buffer.length; 418 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 419 if(newLength>len2 && len2<=len){ 420 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 421 } 422 int[][] copy=null; 423 try { 424 copy=Arrays.copyOf(buffer, len2); 425 } catch (OutOfMemoryError e) { 426 memKill(e); 427 } 428 return copy; 429 } 430 copyOf(long[] buffer, long newLength)431 public static long[] copyOf(long[] buffer, long newLength) { 432 final int len=buffer.length; 433 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 434 if(newLength>len2 && len2<=len){ 435 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 436 } 437 long[] copy=null; 438 try { 439 copy=Arrays.copyOf(buffer, len2); 440 } catch (OutOfMemoryError e) { 441 memKill(e); 442 } 443 return copy; 444 } 445 copyAndFill(long[] buffer, long newLength, int fillValue)446 public static long[] copyAndFill(long[] buffer, long newLength, int fillValue) { 447 final long[] copy=copyOf(buffer, newLength); 448 Arrays.fill(copy, buffer.length, copy.length, fillValue); 449 return copy; 450 } 451 copyOf(long[][] buffer, long newLength)452 public static long[][] copyOf(long[][] buffer, long newLength) { 453 final int len=buffer.length; 454 final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); 455 if(newLength>len2 && len2<=len){ 456 exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); 457 } 458 long[][] copy=null; 459 try { 460 copy=Arrays.copyOf(buffer, len2); 461 } catch (OutOfMemoryError e) { 462 memKill(e); 463 } 464 return copy; 465 } 466 467 /*--------------------------------------------------------------*/ 468 copyOfRange(byte[] buffer, int from, int to)469 public static byte[] copyOfRange(byte[] buffer, int from, int to) { 470 byte[] copy=null; 471 try { 472 copy=Arrays.copyOfRange(buffer, from, to); 473 } catch (OutOfMemoryError e) { 474 memKill(e); 475 } 476 return copy; 477 } 478 copyOfRange(int[] buffer, int start, int limit)479 public static int[] copyOfRange(int[] buffer, int start, int limit) { 480 int[] copy=null; 481 try { 482 copy=Arrays.copyOfRange(buffer, start, limit); 483 } catch (OutOfMemoryError e) { 484 memKill(e); 485 } 486 return copy; 487 } 488 copyOfRange(long[] buffer, int start, int limit)489 public static long[] copyOfRange(long[] buffer, int start, int limit) { 490 long[] copy=null; 491 try { 492 copy=Arrays.copyOfRange(buffer, start, limit); 493 } catch (OutOfMemoryError e) { 494 memKill(e); 495 } 496 return copy; 497 } 498 499 /*--------------------------------------------------------------*/ 500 501 private final double maxSeconds; 502 private final double minLoad; 503 504 private static AtomicBoolean shutdownFlag=new AtomicBoolean(false); 505 private static AtomicBoolean killFlag=new AtomicBoolean(false); 506 private static int count=0; 507 private static KillSwitch ks; 508 private static boolean suppressMessages=false; 509 510 /*--------------------------------------------------------------*/ 511 512 private static final String MemKillMessage=new String("\nThis program ran out of memory.\n" 513 + "Try increasing the -Xmx flag and using tool-specific memory-related parameters."); 514 addBallast()515 public static void addBallast() { 516 synchronized(KillSwitch.class){ 517 ballast=new int[20000]; 518 ballast2=new int[20000]; 519 ballast[0]=1; 520 assert(ballast[0]==1); 521 } 522 } 523 524 private static int[] ballast; 525 private static int[] ballast2; 526 527 } 528