001: /*
002: * @(#)Warmup.java 1.24 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package sun.mtask;
027:
028: import java.io.*;
029: import java.net.*;
030: import java.util.*;
031: import java.lang.reflect.*;
032:
033: import sun.misc.JIT;
034: import sun.misc.CVM;
035:
036: //
037: // A generic warmup module that works with lists of classes to
038: // pre-load, and methods to pre-compile.
039: //
040: // Each list is in its own file
041: //
042: public class Warmup {
043: private static String classNamesFileString = null;
044: private static String memberNamesFileString = null;
045: private static String classNamesFiles[] = null;
046: private static String memberNamesFiles[] = null;
047: private static ClassLoader currClassLoader = null;
048: private static ClassLoader midpClassLoader = null;
049: private static String midpPathString = System.getProperty(
050: "sun.midp.home.path", "midp/midp_fb")
051: + "/classes.zip";
052: private static File midpPath[] = null;
053:
054: private static boolean verbose = (System
055: .getProperty("cdcams.verbose") != null)
056: && (System.getProperty("cdcams.verbose").toLowerCase()
057: .equals("true"));
058:
059: //
060: // The entry point of the warm-up program
061: // arg[0] is a filename containing a list of classes to load and initialize
062: // arg[1] is a filename containing a list of methods to pre-compile
063: //
064: public static void main(String[] args) {
065: processOptions(args);
066: runit(classNamesFileString, memberNamesFileString);
067: }
068:
069: private static void processOptions(String[] args) {
070: classNamesFileString = null;
071: memberNamesFileString = null;
072: for (int i = 0; i < args.length; i++) {
073: if (args[i].equals("-initClasses")) {
074: classNamesFileString = args[++i];
075: classNamesFiles = split(classNamesFileString);
076: } else if (args[i].equals("-precompileMethods")) {
077: memberNamesFileString = args[++i];
078: memberNamesFiles = split(memberNamesFileString);
079: } else {
080: if (verbose) {
081: System.err.println("UNRECOGNIZED OPTION \""
082: + args[i] + "\"");
083: }
084: }
085: }
086: }
087:
088: //
089: // Set current classloader, which is used to load warmup classes.
090: //
091: private static void setCurrClassLoader(String loaderString)
092: throws IOException {
093: String clname = loaderString.substring(12);
094: if (clname == null || clname.equals("")) {
095: /* The current classloader is the null ClassLoader */
096: currClassLoader = null;
097: } else if (clname.equals("sun.misc.Launcher$AppClassLoader")) {
098: /* The current classloader is the AppClassLoader */
099: currClassLoader = ClassLoader.getSystemClassLoader();
100: } else if (clname
101: .equals("sun.misc.MIDPImplementationClassLoader")) {
102: if (midpClassLoader == null) {
103: if (midpPath == null) {
104: StringTokenizer mp = new StringTokenizer(
105: midpPathString, System.getProperty(
106: "path.separator", ":"));
107: int num = mp.countTokens();
108: midpPath = new File[num];
109: for (int i = 0; i < num; i++) {
110: midpPath[i] = new File(mp.nextToken());
111: }
112: }
113: /*
114: * Create the MIDPImplementationClassLoader.
115: * Use reflection to avoid hard-coded references
116: * to dual-stack APIs, which are conditionally
117: * included.
118: */
119: try {
120: Class midpconfig = Class
121: .forName("sun.misc.MIDPConfig");
122: Class args[] = { midpPath.getClass() };
123: Method newMIDPCL = midpconfig.getMethod(
124: "newMIDPImplementationClassLoader", args);
125: Object args2[] = { midpPath };
126: midpClassLoader = (ClassLoader) newMIDPCL.invoke(
127: null, args2);
128: } catch (ClassNotFoundException ce) {
129: throw new IOException(
130: "Cannot find required classloader: "
131: + clname);
132: } catch (NoSuchMethodException me) {
133: me.printStackTrace();
134: throw new IOException(
135: "Cannot find required classloader: "
136: + clname);
137: } catch (IllegalAccessException ie) {
138: ie.printStackTrace();
139: throw new IOException(
140: "Cannot find required classloader: "
141: + clname);
142: } catch (InvocationTargetException ite) {
143: ite.printStackTrace();
144: throw new IOException(
145: "Cannot find required classloader: "
146: + clname);
147: }
148: }
149: currClassLoader = midpClassLoader;
150: } else {
151: throw new IOException("unrecognized classloader: " + clname);
152: }
153:
154: if (verbose) {
155: System.err.println("Set " + currClassLoader
156: + " as the current classloader");
157: }
158: }
159:
160: //
161: // Read a list of elements and return it as a String[]
162: //
163: private static String[] readElements(BufferedReader inReader)
164: throws IOException {
165: /* Reset currClassLoader for the new list */
166: currClassLoader = null;
167:
168: java.util.Vector v = new java.util.Vector();
169: java.io.StreamTokenizer in;
170: in = new StreamTokenizer(inReader);
171: in.resetSyntax();
172: in.eolIsSignificant(false);
173: in.whitespaceChars(0, 0x20);
174: in.wordChars('!', '~');
175: in.commentChar('#');
176:
177: while (in.nextToken() != java.io.StreamTokenizer.TT_EOF) {
178: if (in.sval.startsWith("CLASSLOADER=")) {
179: /* CLASSLOADER indicates which classloader should
180: * be used to load classes in the list.
181: */
182: setCurrClassLoader(in.sval);
183: } else {
184: /* Add class name */
185: v.addElement(in.sval);
186: }
187: }
188:
189: int n = v.size();
190: String olist[] = new String[n];
191: v.copyInto(olist);
192: return olist;
193: }
194:
195: static Class getClassFromName(String className, boolean init) {
196: Class c = null;
197: try {
198: // Load and maybe initialize class
199: c = Class.forName(className, init, currClassLoader);
200: } catch (ClassNotFoundException e) {
201: return null;
202: }
203: return c;
204: }
205:
206: //
207: // If 'init' is not mentioned, assume it's false.
208: // That's the desired behaviour when looking up argument lists.
209: //
210: static Class getClassFromName(String className) {
211: return getClassFromName(className, false);
212: }
213:
214: //
215: // Read class or method list from file.
216: //
217: private static String[] readLists(String fileName) {
218: String[] list = null;
219: BufferedReader in;
220:
221: try {
222: in = new BufferedReader(new FileReader(fileName));
223: list = readElements(in);
224: if (verbose) {
225: System.err
226: .println("read from " + fileName + " done...");
227: }
228: in.close();
229: return list;
230: } catch (IOException e) {
231: if (verbose) {
232: System.err.println("read from " + fileName
233: + " failed...");
234: }
235: e.printStackTrace();
236: return null;
237: }
238: }
239:
240: //
241: // Initialize classes from the list.
242: //
243: private static boolean processClasses(String classes[]) {
244: if (verbose) {
245: System.err.println("CLASSES TO INITIALIZE");
246: }
247:
248: if (classes != null) {
249: for (int i = 0; i < classes.length; i++) {
250: // Load and initialize class
251: Class cl = getClassFromName(classes[i], true);
252: //DEBUG: System.err.println((i+1)+":\t "+cl);
253: if (cl == null) {
254: if (verbose) {
255: System.err.println("\nCould not find class "
256: + classes[i]);
257: }
258: return false;
259: }
260: }
261: }
262: return true;
263: }
264:
265: //
266: // Parsing methods is somewhat more complex.
267: //
268: // If we see a class name in the method list, we compile
269: // all the methods in it.
270: //
271: // If we see a method name, we parse it, and then pass it on to
272: // JIT.compileMethod().
273: //
274: private static boolean processPrecompilation(
275: String[] memberNameFiles) {
276: int i;
277:
278: if (!CVM.isCompilerSupported()) {
279: if (verbose) {
280: System.err
281: .println("Compiler not supported, cannot precompile");
282: }
283: return false;
284: }
285:
286: // initialized AOT code
287: CVM.initializeAOTCode();
288:
289: for (i = 0; i < memberNamesFiles.length; i++) {
290: if (verbose) {
291: System.err
292: .println("membersFile=" + memberNamesFiles[i]);
293: System.err.println("reading methods...");
294: }
295: String methods[] = readLists(memberNamesFiles[i]);
296:
297: // Parse and precompile
298: if (methods != null) {
299: for (int j = 0; j < methods.length; j++) {
300: // Upon error, fail and return.
301: if (!parseAndPrecompileMethods(methods[j])) {
302: CVM.markCodeBuffer(); // mark shared codecache
303: CVM.initializeJITPolicy();
304: return false;
305: }
306: }
307: }
308: }
309:
310: // mark shared codecache
311: CVM.markCodeBuffer();
312:
313: // initialize JIT policy
314: CVM.initializeJITPolicy();
315: return true;
316: }
317:
318: static private int mLineNo = 1;
319:
320: private static boolean parseAndPrecompileMethods(String s) {
321: // First off replace all '/' by '.'. This saves us the trouble
322: // of converting these for each signature string found.
323: s = s.replace('/', '.');
324: if (s.indexOf('(') == -1) {
325: // Looks like a class. Check
326: Class c = getClassFromName(s);
327: if (c == null) {
328: if (verbose) {
329: System.err.println("Class " + s + " not found");
330: }
331: return false;
332: }
333: // It is a class. Find all of its declared methods...
334: Method[] cmethods = c.getDeclaredMethods();
335: if (cmethods == null) {
336: if (verbose) {
337: System.err
338: .println("Could not get methods in class "
339: + s);
340: }
341: return false;
342: }
343: for (int i = 0; i < cmethods.length; i++) {
344: /* System.err.println(mLineNo+":\t"+cmethods[i]); */
345: mLineNo++;
346: if (!JIT.compileMethod(cmethods[i], false)) {
347: if (verbose) {
348: System.err.println("Failed to compile "
349: + cmethods[i]);
350: }
351: return false;
352: }
353: //methods[index].addElement(cmethods[i]);
354: }
355: // And find all of its declared constructors...
356: Constructor[] cconstructors = c.getDeclaredConstructors();
357: if (cconstructors == null) {
358: if (verbose) {
359: System.err
360: .println("Could not get constructors in class "
361: + s);
362: }
363: return false;
364: }
365: for (int i = 0; i < cconstructors.length; i++) {
366: /* System.err.println(mLineNo+":\t"+cconstructors[i]); */
367: mLineNo++;
368: if (!JIT.compileMethod(cconstructors[i], false)) {
369: if (verbose) {
370: System.err.println("Failed to compile "
371: + cconstructors[i]);
372: }
373: return false;
374: }
375: // methods[index].addElement(cconstructors[i]);
376: }
377: } else {
378: Member m = parseMethod(s);
379: if (m == null) {
380: if (verbose) {
381: System.err.println("Could not find method " + s);
382: }
383: return false;
384: } else {
385: //DEBUG: System.err.println(mLineNo+":\t"+m);
386: mLineNo++;
387: if (!JIT.compileMethod(m, false)) {
388: if (verbose) {
389: System.err.println("Failed to compile " + m);
390: }
391: return false;
392: }
393: }
394: // methods[index].addElement(m);
395: }
396: return true;
397: }
398:
399: //
400: // Parse a string describing a method or constructor, and return a
401: // Member object
402: //
403: private static Member parseMethod(String s) {
404: //
405: // We are looking at a method. Parse that
406: //
407: int beginArgs = s.indexOf('(');
408: int endArgs = s.indexOf(')', beginArgs + 1);
409: if (endArgs == -1) {
410: if (verbose) {
411: System.err.println("Missing ')' in " + s);
412: }
413: return null;
414: }
415: if (false) {
416: // There is no real need to print out this warning
417: if (endArgs < s.length() - 1) {
418: if (verbose) {
419: System.err.println("Ignoring return type "
420: + s.substring(endArgs + 1));
421: }
422: }
423: }
424:
425: int methodDot = s.lastIndexOf('.', beginArgs);
426: if (methodDot == -1) {
427: if (verbose) {
428: System.err.println("Couldn't find method name in " + s);
429: }
430: return null;
431: }
432: String signature = s.substring(beginArgs, endArgs + 1);
433: String className = s.substring(0, methodDot);
434: String methodName = s.substring(methodDot + 1, beginArgs);
435: Class parentClass = getClassFromName(className);
436:
437: if (parentClass == null) {
438: if (verbose) {
439: System.err.println("Class " + className + " not found");
440: }
441: return null;
442: }
443: Class[] args = parseArglist(signature);
444: if (args == null) {
445: if (verbose) {
446: System.err
447: .println("Could not parse arguments in signature: "
448: + signature);
449: }
450: return null;
451: }
452: Member this Method = null;
453: try {
454: // There is no way to find <clinit> using reflection...
455: if (methodName.equals("<init>")) {
456: this Method = parentClass.getDeclaredConstructor(args);
457: } else {
458: this Method = parentClass.getDeclaredMethod(methodName,
459: args);
460: }
461: } catch (Throwable t0) {
462: return null;
463: }
464: return this Method;
465: }
466:
467: //
468: // Given a signature string, return an array of classes for
469: // each element of the signature, to be used by reflection code.
470: //
471: private static Class[] parseArglist(String signature) {
472: Vector v = new Vector();
473: int pos = 1;
474: int endpos = signature.length() - 1;
475: while (pos < endpos) {
476: int arrayDepth = 0;
477: Class targetClass = null;
478: while (signature.charAt(pos) == '[') {
479: arrayDepth++;
480: pos++;
481: }
482: switch (signature.charAt(pos)) {
483: case 'I':
484: targetClass = Integer.TYPE;
485: pos++;
486: break;
487: case 'S':
488: targetClass = Short.TYPE;
489: pos++;
490: break;
491: case 'C':
492: targetClass = Character.TYPE;
493: pos++;
494: break;
495: case 'Z':
496: targetClass = Boolean.TYPE;
497: pos++;
498: break;
499: case 'B':
500: targetClass = Byte.TYPE;
501: pos++;
502: break;
503: case 'F':
504: targetClass = Float.TYPE;
505: pos++;
506: break;
507: case 'D':
508: targetClass = Double.TYPE;
509: pos++;
510: break;
511: case 'J':
512: targetClass = Long.TYPE;
513: pos++;
514: break;
515: case 'L':
516: int semi = signature.indexOf(';', pos);
517: if (semi == -1) {
518: if (verbose) {
519: System.err.println("L not followed by ; in "
520: + signature);
521: }
522: return null;
523: }
524: String targetName;
525: targetName = signature.substring(pos + 1, semi);
526:
527: targetClass = getClassFromName(targetName);
528: if (targetClass == null) {
529: if (verbose) {
530: System.err.println("COULD NOT FIND TARGET="
531: + targetName);
532: }
533: return null;
534: }
535: pos = semi + 1;
536: break;
537: default:
538: if (verbose) {
539: System.err.println("Unexpected '"
540: + signature.charAt(pos) + "' in signature");
541: }
542: return null;
543: }
544: if (arrayDepth > 0) {
545: // this is grotesque
546: // make a 1 x 1 x 1 x 1 x 1 x ... array of foo.
547: // then get its class.
548: int lArray[] = new int[arrayDepth];
549: for (int i = 0; i < arrayDepth; i++) {
550: lArray[i] = 1;
551: }
552: try {
553: Object arrayOfThing = java.lang.reflect.Array
554: .newInstance(targetClass, lArray);
555: targetClass = arrayOfThing.getClass();
556: } catch (Throwable t) {
557: if (verbose) {
558: System.err
559: .println("Could not instantiate (or get class of) "
560: + arrayDepth
561: + "-dimensional array of "
562: + targetClass.toString());
563: }
564: return null;
565: }
566: }
567: v.addElement(targetClass);
568: }
569: Class[] args = new Class[v.size()];
570: v.copyInto(args);
571: return args;
572: }
573:
574: //
575: // Split path string into separate String components.
576: //
577: private static String[] split(String pathString) {
578: if (pathString != null) {
579: StringTokenizer components = new StringTokenizer(
580: pathString, System.getProperty("path.separator",
581: ":"));
582: int num = components.countTokens();
583: String paths[] = new String[num];
584: for (int i = 0; i < num; i++) {
585: paths[i] = components.nextToken();
586: }
587: return paths;
588: } else {
589: return null;
590: }
591: }
592:
593: public static void runit(String cnfs, String mnfs) {
594: int i;
595:
596: // Class name lists
597: if (cnfs != null && !cnfs.equals(classNamesFileString)) {
598: classNamesFileString = cnfs;
599: classNamesFiles = split(cnfs);
600: }
601: if (classNamesFiles != null) {
602: String[] classlist;
603: for (i = 0; i < classNamesFiles.length; i++) {
604: if (verbose) {
605: System.err.println("classesFile="
606: + classNamesFiles[i]);
607: System.err.println("reading classes...");
608: }
609: classlist = readLists(classNamesFiles[i]);
610: if (processClasses(classlist)) {
611: if (verbose) {
612: System.err
613: .println("processing classes done...");
614: }
615: } else {
616: if (verbose) {
617: System.err
618: .println("processing classes failed...");
619: }
620: }
621: }
622: }
623:
624: // Method lists
625: if (mnfs != null && !mnfs.equals(memberNamesFileString)) {
626: memberNamesFileString = mnfs;
627: memberNamesFiles = split(mnfs);
628: }
629: if (memberNamesFiles != null) {
630: if (processPrecompilation(memberNamesFiles)) {
631: if (verbose) {
632: System.err.println("processing methods done...");
633: }
634: } else {
635: if (verbose) {
636: System.err.println("processing methods failed...");
637: }
638: }
639: }
640: }
641: }
|