📄 monitor.java~
字号:
/* * Monitor.java * * Created on June 21, 2001, 8:20 AM * * See LICENSE file for license conditions. */package residue.runtime;import java.io.*;/** * This class contains everything needed for instrumentation * in other programs to be executed. It also contains a couple * related helper methods, but care was taken to ensure that * this class remained relatively small, so as to not adversely * affect the size of a distributed application. * * @author chowells * @version */public class Monitor{ public static boolean [] hitTable; private static boolean initialized; private static Thread hook; private static boolean getcalled; private static String htname; private static String ltname; private static int size = -1; /** * This method initializes the hit table. It does so by * reading in the .config file, getting the size needed for * the array, creating the array, and registering a * shutdownHook to write out the table when the VM shuts down. */ // not sure synchronization was really necessary, but it shouldn't // hurt something that will be called so rarely public synchronized static void init(String path) throws IOException { if (initialized) return; initialized = true; getNames(path); hitTable = new boolean[size]; hook = new Thread(new Runnable() { public void run() { dump(); } // run }); // anonymous Runnable Runtime.getRuntime().addShutdownHook(hook); } // init /** * This method initializes the hit table regardless of whether * it was previously initialized, and doesn't add the shutdown hook. * This method was added in order to make integrating Gretel and JUnit * easier, at the request of martijn@kruithof.xs4all.nl. */ public synchronized static void manualInit(String path) throws IOException { hitTable = null; getcalled = false; htname = null; ltname = null; size = -1; initialized=true; getNames(path); hitTable = new boolean[size]; } // manualInit /** * Writes out the hit table to the location given in the .config * file. If there is already a hit table at that location, it * reads it in, ORing each entry with the current entry, before * writing it out. As this is a somewhat performance dependent * process, as it is run by a ShutdownHook, it has been timed. * Table sizes of one million entries have been tested, with * the IO time under one second, so it is believed to be * fast enough. */ public static void dump() { if (htname != null) { try { DataInputStream din = new DataInputStream(new BufferedInputStream(new FileInputStream(htname))); for (int i = 0; i < size; i++) hitTable[i] |= din.readBoolean(); din.close(); } catch (Exception e) {} try { DataOutputStream dout = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(htname))); for(int i = 0; i < hitTable.length; i++) dout.writeBoolean(hitTable[i]); dout.close(); } catch (IOException e) {} } // if } // dump /** * Returns the CURRENT contents of the hitTable. */ public static boolean [] getHitTable() { if (!getcalled) throw new IllegalStateException("No configuration file loaded."); try { boolean [] result = new boolean[size]; DataInputStream din = new DataInputStream(new BufferedInputStream(new FileInputStream(htname))); for (int i = 0; i < size; i++) result[i] = din.readBoolean(); din.close(); return result; } catch (Exception e) { if (size > 0) return new boolean[size]; else return new boolean[0]; } } // getHitTable public static String getHitTableName() { if (!getcalled) throw new IllegalStateException("No configuration file loaded."); return htname; } // getHitTableName public static void setHitTableName(String s) { htname = s; getcalled = true; } // setHitTableName public static String getLineTableName() { if (!getcalled) throw new IllegalStateException("No configuration file loaded."); return ltname; } // getLineTableName public static void setLineTableName(String s) { ltname = s; getcalled = true; } // setLineTableName public static int getSize() { if (!getcalled) throw new IllegalStateException("No configuration file loaded."); return size; } // getSize public static void setSize(int i) { size = i; getcalled = true; } // setSize /** * Writes out the current internal representation of the * contents of the configuration file. Throws an IllegalStateException * if the contents of the table haven't been set or read in. */ public synchronized static void writeNames(String path) throws IOException { if (!getcalled) throw new IllegalStateException("No values have been set"); String filename = path.concat(".gretel"); PrintWriter p = new PrintWriter(new BufferedWriter(new FileWriter(filename))); if (htname != null) { p.print("hitTableName "); p.println(filter(htname)); } if (ltname != null) { p.print("lineTableName "); p.println(filter(ltname)); } if (size != -1) { p.print("tableSize "); p.println(size); } p.close(); } // writeNames /** * This method provides the ability to read the .config file from a * uniform place. Use the corresponding writeNames() method to * store changes back into the .config file. */ // this is the one that needs to be synchronized to prevent // multiple reads public synchronized static void getNames(String path) throws IOException { getcalled = true; ltname = null; htname = null; size = -1; Reader r; if (path.endsWith(".gretel")) { r = new BufferedReader(new FileReader(path)); } else { try { r = new BufferedReader(new InputStreamReader( ClassLoader.getSystemResourceAsStream(path.concat(".gretel")))); } catch (NullPointerException ne) { return; } } StreamTokenizer tok = new StreamTokenizer(r); tok.wordChars('!', '~'); tok.ordinaryChar('"'); tok.quoteChar('"'); do { tok.nextToken(); if (tok.ttype == tok.TT_WORD) { String word = tok.sval; tok.nextToken(); if (word.equalsIgnoreCase("tablesize")) { if (size == -1 && tok.ttype == tok.TT_NUMBER) size = (int)tok.nval; } else if (word.equalsIgnoreCase("hittablename")) { if (htname == null && (tok.ttype == '"' || tok.ttype == tok.TT_WORD)) htname = expand(tok.sval); } else if (word.equalsIgnoreCase("linetablename")) { if (ltname == null && (tok.ttype == '"' || tok.ttype == tok.TT_WORD)) ltname = expand(tok.sval); } } // if } while (tok.ttype != tok.TT_EOF); r.close(); } // getNames /** * This method expands any instances of "$home" in the input * string to the string in the "user.home" property as defined * by System.getProperty. */ public static String expand(String s) { int i = s.toLowerCase().indexOf("$home"); if (i < 0) return s; StringBuffer result = new StringBuffer(); result.append(s.substring(0, i)); result.append(System.getProperty("user.home")); result.append(expand(s.substring(i + 5))); return result.toString(); } // expand /** * This method converts any instances of \ or " in the * string it is given to \\ or \", respectively, and puts * double quotes around the string. This is used to * generate the output string that will be parsed * correctly in getNames above. */ public static String filter(String s) { StringBuffer result = new StringBuffer(); result.append('"'); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '\\' || c == '"') { result.append('\\'); } result.append(c); } // for result.append('"'); return result.toString(); } // filter /** * This is the method inserted by the instrumentation, to * record execution of a given probe. */ public static void hit(int index) { hitTable[index] = true; } // hit } // class Monitor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -