jpayne@68: package shared; jpayne@68: jpayne@68: import java.lang.management.ManagementFactory; jpayne@68: import java.lang.management.OperatingSystemMXBean; jpayne@68: import java.util.Arrays; jpayne@68: //import com.sun.management.OperatingSystemMXBean; jpayne@68: import java.util.concurrent.atomic.AtomicBoolean; jpayne@68: import java.util.concurrent.atomic.AtomicIntegerArray; jpayne@68: jpayne@68: /** jpayne@68: * Monitors CPU utilization to determine if the program has crashed. jpayne@68: * Also performs VM forced shutdowns and safe memory allocation. jpayne@68: * @author Brian Bushnell jpayne@68: * @date Feb 25, 2015 jpayne@68: * jpayne@68: */ jpayne@68: public final class KillSwitch extends Thread { jpayne@68: jpayne@68: public static void main(String[] args){ jpayne@68: double seconds=Double.parseDouble(args[0]); jpayne@68: double load=Double.parseDouble(args[1]); jpayne@68: launch(seconds, load); jpayne@68: if(args.length>2){ jpayne@68: jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: private KillSwitch(double seconds, double load) { jpayne@68: maxSeconds=seconds; jpayne@68: minLoad=load; jpayne@68: } jpayne@68: jpayne@68: public static boolean launch(){ jpayne@68: return launch(600); jpayne@68: } jpayne@68: jpayne@68: public static boolean launch(double seconds){ jpayne@68: return launch(seconds, 0.002); jpayne@68: } jpayne@68: jpayne@68: public static synchronized boolean launch(double seconds, double load){ jpayne@68: if(count>0){return false;} jpayne@68: ks=new KillSwitch(seconds, load); jpayne@68: ks.start(); jpayne@68: return true; jpayne@68: } jpayne@68: jpayne@68: @Override jpayne@68: public void run(){ jpayne@68: jpayne@68: boolean success=monitor(); jpayne@68: // System.err.println("success: "+success); jpayne@68: if(!success || killFlag.get()){ jpayne@68: if(!suppressMessages){ jpayne@68: System.err.println("Process has decided it has crashed, and will abort.\n" + jpayne@68: "If this decision was incorrect, please re-run with the flag 'monitor=f'"); jpayne@68: } jpayne@68: kill0(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: private boolean monitor(){ jpayne@68: jpayne@68: final OperatingSystemMXBean bean=ManagementFactory.getOperatingSystemMXBean(); jpayne@68: if(bean.getSystemLoadAverage()<0){ jpayne@68: System.err.println("This OS does not support monitor, so monitoring was disabled."); jpayne@68: return true; jpayne@68: } jpayne@68: jpayne@68: final long start=System.currentTimeMillis(); jpayne@68: final long buffer=(long)(1+maxSeconds*1000); jpayne@68: long stop=start+buffer; jpayne@68: // System.err.println("start="+start+", stop="+stop+", buffer="+buffer); jpayne@68: // System.err.println("shutdownFlag.get()="+shutdownFlag.get()); jpayne@68: while(!shutdownFlag.get()){ jpayne@68: try { jpayne@68: sleep(500); jpayne@68: } catch (InterruptedException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: final double load=bean.getSystemLoadAverage(); jpayne@68: final long time=System.currentTimeMillis(); jpayne@68: if(load>minLoad){stop=time+buffer;} jpayne@68: if(time>stop){return false;} jpayne@68: // System.err.println("stop-time="+(stop-time)+", load="+load); jpayne@68: } jpayne@68: // System.err.println("shutdownFlag.get()="+shutdownFlag.get()); jpayne@68: return true; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static synchronized void kill(String s){ jpayne@68: ballast=null; jpayne@68: Exception e=new Exception(s); jpayne@68: e.printStackTrace(); jpayne@68: kill0(); jpayne@68: } jpayne@68: jpayne@68: // public static void kill(Throwable e){ jpayne@68: // e.printStackTrace(); jpayne@68: // kill0(); jpayne@68: // } jpayne@68: jpayne@68: public static synchronized void kill(){ jpayne@68: ballast=null; jpayne@68: Exception e=new Exception("Aborting."); jpayne@68: e.printStackTrace(); jpayne@68: kill0(); jpayne@68: } jpayne@68: jpayne@68: public static synchronized void killSilent(){ jpayne@68: ballast=null; jpayne@68: kill0(); jpayne@68: } jpayne@68: jpayne@68: private static void kill0(){ jpayne@68: ballast=null; jpayne@68: Runtime.getRuntime().halt(1); jpayne@68: } jpayne@68: jpayne@68: public static void shutdown(){ jpayne@68: shutdownFlag.set(true); jpayne@68: } jpayne@68: jpayne@68: public static void setKillFlag(){ jpayne@68: killFlag.set(true); jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static final void throwableKill(Throwable e){ jpayne@68: ballast=null; jpayne@68: synchronized(MemKillMessage){ jpayne@68: e.printStackTrace(); jpayne@68: kill0(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: public static final void exceptionKill(Exception e){ jpayne@68: ballast=null; jpayne@68: synchronized(MemKillMessage){ jpayne@68: e.printStackTrace(); jpayne@68: kill0(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: public static final void memKill(OutOfMemoryError e){ jpayne@68: ballast=null; jpayne@68: synchronized(MemKillMessage){ jpayne@68: e.printStackTrace(); jpayne@68: System.err.println(MemKillMessage); jpayne@68: // Shared.printMemory(); jpayne@68: // killSilent(); jpayne@68: kill0(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: public static final void assertionKill(AssertionError e){ jpayne@68: ballast=null; jpayne@68: synchronized(MemKillMessage){ jpayne@68: // System.err.println(e); jpayne@68: e.printStackTrace(); jpayne@68: kill0(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static final AtomicIntegerArray allocAtomicInt(int len){ jpayne@68: AtomicIntegerArray ret=null; jpayne@68: try { jpayne@68: ret=new AtomicIntegerArray(len); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final long[] allocLong1D(int len){ jpayne@68: long[] ret=null; jpayne@68: try { jpayne@68: ret=new long[len]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final int[] allocInt1D(int len){ jpayne@68: int[] ret=null; jpayne@68: try { jpayne@68: ret=new int[len]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static float[] allocFloat1D(int len) { jpayne@68: float[] ret=null; jpayne@68: try { jpayne@68: ret=new float[len]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static double[] allocDouble1D(int len) { jpayne@68: double[] ret=null; jpayne@68: try { jpayne@68: ret=new double[len]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final byte[] allocByte1D(int len){ jpayne@68: byte[] ret=null; jpayne@68: try { jpayne@68: ret=new byte[len]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final char[] allocChar1D(int len){ jpayne@68: char[] ret=null; jpayne@68: try { jpayne@68: ret=new char[len]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static final int[][] allocInt2D(int x){ jpayne@68: int[][] ret=null; jpayne@68: try { jpayne@68: ret=new int[x][]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final int[][] allocInt2D(int x, int y){ jpayne@68: int[][] ret=null; jpayne@68: try { jpayne@68: ret=new int[x][y]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: ballast2=null; jpayne@68: System.err.print(x+","+y); jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final float[][] allocFloat2D(int x){ jpayne@68: float[][] ret=null; jpayne@68: try { jpayne@68: ret=new float[x][]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final float[][] allocFloat2D(int x, int y){ jpayne@68: float[][] ret=null; jpayne@68: try { jpayne@68: ret=new float[x][y]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: ballast2=null; jpayne@68: System.err.print(x+","+y); jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final long[][] allocLong2D(int x){ jpayne@68: long[][] ret=null; jpayne@68: try { jpayne@68: ret=new long[x][]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static final long[][] allocLong2D(int x, int y){ jpayne@68: long[][] ret=null; jpayne@68: try { jpayne@68: ret=new long[x][y]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static int[][][] allocInt3D(int x) { jpayne@68: int[][][] ret=null; jpayne@68: try { jpayne@68: ret=new int[x][][]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static int[][][] allocInt3D(int x, int y) { jpayne@68: int[][][] ret=null; jpayne@68: try { jpayne@68: ret=new int[x][y][]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: public static int[][][] allocInt3D(int x, int y, int z) { jpayne@68: int[][][] ret=null; jpayne@68: try { jpayne@68: ret=new int[x][y][z]; jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return ret; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static byte[] copyOf(byte[] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: byte[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static float[] copyOf(float[] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: float[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static double[] copyOf(double[] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: double[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * Copy the buffer into an array of size newLength. jpayne@68: * Fill extra cells with fillValue. jpayne@68: * @param buffer Old array jpayne@68: * @param newLength Length of new array jpayne@68: * @param fillValue Value to insert in extra cells jpayne@68: * @return New array jpayne@68: */ jpayne@68: public static int[] copyAndFill(int[] buffer, long newLength, int fillValue) { jpayne@68: final int[] copy=copyOf(buffer, newLength); jpayne@68: Arrays.fill(copy, buffer.length, copy.length, fillValue); jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static int[] copyOf(int[] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: int[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static int[][] copyOf(int[][] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: int[][] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static long[] copyOf(long[] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: long[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static long[] copyAndFill(long[] buffer, long newLength, int fillValue) { jpayne@68: final long[] copy=copyOf(buffer, newLength); jpayne@68: Arrays.fill(copy, buffer.length, copy.length, fillValue); jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static long[][] copyOf(long[][] buffer, long newLength) { jpayne@68: final int len=buffer.length; jpayne@68: final int len2=(int)Tools.min(newLength, Shared.MAX_ARRAY_LEN); jpayne@68: if(newLength>len2 && len2<=len){ jpayne@68: exceptionKill(new Exception("Tried to create an array above length limit: "+len+"," +newLength)); jpayne@68: } jpayne@68: long[][] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOf(buffer, len2); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: public static byte[] copyOfRange(byte[] buffer, int from, int to) { jpayne@68: byte[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOfRange(buffer, from, to); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static int[] copyOfRange(int[] buffer, int start, int limit) { jpayne@68: int[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOfRange(buffer, start, limit); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: public static long[] copyOfRange(long[] buffer, int start, int limit) { jpayne@68: long[] copy=null; jpayne@68: try { jpayne@68: copy=Arrays.copyOfRange(buffer, start, limit); jpayne@68: } catch (OutOfMemoryError e) { jpayne@68: memKill(e); jpayne@68: } jpayne@68: return copy; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: private final double maxSeconds; jpayne@68: private final double minLoad; jpayne@68: jpayne@68: private static AtomicBoolean shutdownFlag=new AtomicBoolean(false); jpayne@68: private static AtomicBoolean killFlag=new AtomicBoolean(false); jpayne@68: private static int count=0; jpayne@68: private static KillSwitch ks; jpayne@68: private static boolean suppressMessages=false; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: private static final String MemKillMessage=new String("\nThis program ran out of memory.\n" jpayne@68: + "Try increasing the -Xmx flag and using tool-specific memory-related parameters."); jpayne@68: jpayne@68: public static void addBallast() { jpayne@68: synchronized(KillSwitch.class){ jpayne@68: ballast=new int[20000]; jpayne@68: ballast2=new int[20000]; jpayne@68: ballast[0]=1; jpayne@68: assert(ballast[0]==1); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: private static int[] ballast; jpayne@68: private static int[] ballast2; jpayne@68: jpayne@68: }