/* * and as a public service to ClassEntry... */ ClassInfo findClassInfo(String cname) { InputStream fin = finder.findClassFile(cname); if (fin == null) return null; ClassFile cfile = new ClassFile(cname, fin, false); if (!cfile.readClassFile()) { cfile.dump(System.err); return null; } return cfile.cinfo; }
public static void load(ClassData k) throws ClassNotFoundException, IOException { ClassData kp; String sname; sname = k.supername; // name of superclass if (k.superclass == null && sname != null) { // there is a superclass and it has not been linked in for (kp = previous; kp != null; kp = kp.superclass) if (kp.name.equals(sname)) break; if (kp != null) k.superclass = kp; // found in existing chain else { // not found; find and load superclass from file ClassFile cf = ClassFile.find(sname); k.superclass = ClassData.forStream(null, cf, false); // System.out.println (sname + " from " + cf.dir); /* Resulting class has to have the right name. */ if (!sname.equals(k.superclass.name)) { throw new ClassNotFoundException(sname); } load(k.superclass); // load superclass's superclasses } } k.state = ClassData.RES_SUPERCLASSES; k.buildTables(); // fill in method table IHash.mark(null, k); // mark interfaces previous = k; // remember class just loaded }
/** * @see * org.eclipse.jdt.internal.core.builder.AbstractImageBuilder#writeClassFileContents(org.eclipse.jdt.internal.compiler.ClassFile, * org.eclipse.core.resources.IFile, java.lang.String, boolean, * org.eclipse.jdt.internal.core.builder.SourceFile) */ protected void writeClassFileContents( ClassFile classfile, IFile file, String qualifiedFileName, boolean isTopLevelType, SourceFile compilationUnit) throws CoreException { // Before writing out the class file, compare it to the previous file // If structural changes occurred then add dependent source files byte[] bytes = classfile.getBytes(); if (file.exists()) { if (writeClassFileCheck(file, qualifiedFileName, bytes) || compilationUnit.updateClassFile) { // see 46093 if (JavaBuilder.DEBUG) System.out.println("Writing changed class file " + file.getName()); // $NON-NLS-1$ if (!file.isDerived()) file.setDerived(true, null); file.setContents(new ByteArrayInputStream(bytes), true, false, null); } else if (JavaBuilder.DEBUG) { System.out.println("Skipped over unchanged class file " + file.getName()); // $NON-NLS-1$ } } else { if (isTopLevelType) addDependentsOf(new Path(qualifiedFileName), true); // new type if (JavaBuilder.DEBUG) System.out.println("Writing new class file " + file.getName()); // $NON-NLS-1$ try { file.create(new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null); } catch (CoreException e) { if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) { IStatus status = e.getStatus(); if (status instanceof IResourceStatus) { IPath oldFilePath = ((IResourceStatus) status).getPath(); char[] oldTypeName = oldFilePath.removeFileExtension().lastSegment().toCharArray(); char[][] previousTypeNames = this.newState.getDefinedTypeNamesFor(compilationUnit.typeLocator()); boolean fromSameFile = false; if (previousTypeNames == null) { fromSameFile = CharOperation.equals(compilationUnit.getMainTypeName(), oldTypeName); } else { for (int i = 0, l = previousTypeNames.length; i < l; i++) { if (CharOperation.equals(previousTypeNames[i], oldTypeName)) { fromSameFile = true; break; } } } if (fromSameFile) { // file is defined by the same compilationUnit, but won't be deleted until later so do // it now IFile collision = file.getParent().getFile(new Path(oldFilePath.lastSegment())); collision.delete(true, false, null); boolean success = false; try { file.create( new ByteArrayInputStream(bytes), IResource.FORCE | IResource.DERIVED, null); success = true; } catch (CoreException ignored) { // ignore the second exception } if (success) return; } } // catch the case that a type has been renamed and collides on disk with an // as-yet-to-be-deleted type throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedFileName)); } throw e; // rethrow } } }
/** * Performs the actual editing of a class. Does a whole mess of stuff including reading in the * classfile, building data structures to represent the class file, converting the CFG for each * method in the class into SSA form, perform some anlayses and optimizations on the method, and * finally committing it back to the class file. Phew. */ private static void editClass(final String className) { ClassFile classFile; // Holds info about a class (implements // ClassInfo) // Get information about the class className try { classFile = (ClassFile) Main.context.loadClass(className); } catch (final ClassNotFoundException ex) { System.err.println("** Couldn't find class: " + ex.getMessage()); return; } if (!Main.FORCE) { // Check to see if the file is up-to-date (i.e. has been // recompiled since it was last optimized). If so, do nothing // because the FORCE flag is false. final File source = classFile.file(); final File target = classFile.outputFile(); if ((source != null) && (target != null) && source.exists() && target.exists() && (source.lastModified() < target.lastModified())) { if (Main.VERBOSE) { System.out.println(classFile.name() + " is up to date"); } return; } } if (Main.DEBUG) { // Print the contents of the class file to System.out classFile.print(System.out); } final ClassEditor c = Main.context.editClass(classFile); boolean skip = false; final String name = c.type().className(); final String qual = c.type().qualifier() + "/*"; // Edit only classes explicitly mentioned. if (Main.ONLY.size() > 0) { skip = true; // Only edit classes we explicitly don't name. for (int i = 0; i < Main.ONLY.size(); i++) { final String pkg = (String) Main.ONLY.get(i); if (name.equals(pkg) || qual.equals(pkg)) { skip = false; break; } } } // Don't edit classes we explicitly skip. if (!skip) { for (int i = 0; i < Main.SKIP.size(); i++) { final String pkg = (String) Main.SKIP.get(i); if (name.equals(pkg) || qual.equals(pkg)) { skip = true; break; } } } if (skip) { if (Main.VERBOSE) { System.out.println("Skipping " + c.type().className()); } // We're done with this class file, decrement its reference count Main.context.release(classFile); return; } // Touch the output file first. That is, create the file, but make // it empty, just to make sure we can create it. try { final File f = classFile.outputFile(); if (f.exists()) { f.delete(); } final File dir = new File(f.getParent()); dir.mkdirs(); if (!dir.exists()) { throw new RuntimeException("Couldn't create directory: " + dir); } final DataOutputStream out = new DataOutputStream(new FileOutputStream(f)); new PrintStream(out).println(); out.close(); } catch (final IOException e) { e.printStackTrace(); System.exit(1); } if (Main.VERBOSE) { System.out.println("Optimizing " + c.type().className()); } // Finally, we can start playing with the methods... final MethodInfo[] methods = c.methods(); final int numMethods = methods.length + 1; ; int whichMethod = 0; for (int j = 0; j < methods.length; j++) { final MethodEditor m; try { m = Main.context.editMethod(methods[j]); } catch (final ClassFormatException ex) { System.err.println(ex.getMessage()); continue; } if (Main.TRACE) { whichMethod++; System.out.println( "Optimizing " + name + "." + m.name() + " (method " + whichMethod + " of " + numMethods + ")"); } if (Main.METHOD != null) { // A method name has been specified on the command line using // -only-method. boolean pass = true; String t = m.name() + m.type(); if (t.equals(Main.METHOD)) { pass = false; } t = m.name(); if (t.equals(Main.METHOD)) { pass = false; } if (pass) { // This isn't the method we're looking for. // Decrement its reference count. Main.context.release(methods[j]); continue; } } if (Main.DEBUG) { m.print(System.out); } if (m.isNative() || m.isAbstract()) { // We can't edit native or abstract methods Main.context.release(methods[j]); continue; } Main.bloatMethod(m, Main.context); } if (Main.ANNO) { String s = "Optimized with: EDU.purdue.cs.bloat.optimize.Main"; for (int i = 0; i < Main.ARGS.length; i++) { if ((Main.ARGS[i].indexOf(' ') >= 0) || (Main.ARGS[i].indexOf('\t') >= 0) || (Main.ARGS[i].indexOf('\r') >= 0) || (Main.ARGS[i].indexOf('\n') >= 0)) { s += " '" + Main.ARGS[i] + "'"; } else { s += " " + Main.ARGS[i]; } } System.out.println(s); // c.constants().addConstant(Constant.UTF8, s); } Main.context.commit(classFile); Main.context.release(classFile); if (Main.TRACE) { System.out.println(Main.context.toString()); } }
/** * Adds residency/update/swizzle checks to all of the methods in a given class. * * @param context Information about all the classes we're dealing with * @param info Information about the class we're decorating */ private static void decorateClass(final EditorContext context, final ClassInfo info) { final ClassFile classFile = (ClassFile) info; // Check to see if the class file is up-to-date if (!Main.FORCE) { final File source = classFile.file(); final File target = classFile.outputFile(); if ((source != null) && (target != null) && source.exists() && target.exists() && (source.lastModified() < target.lastModified())) { if (Main.VERBOSE > 1) { System.out.println(classFile.name() + " is up to date"); } return; } } if (Main.VERBOSE > 2) { classFile.print(System.out); } final ClassEditor c = context.editClass(info); boolean skip = false; final String name = c.type().className(); final String qual = c.type().qualifier() + "/*"; // Edit only classes explicitly mentioned. if (Main.ONLY.size() > 0) { skip = true; // Only edit classes we explicitly don't name. for (int i = 0; i < Main.ONLY.size(); i++) { final String pkg = (String) Main.ONLY.get(i); if (name.equals(pkg) || qual.equals(pkg)) { skip = false; break; } } } // Don't edit classes we explicitly skip. if (!skip) { for (int i = 0; i < Main.SKIP.size(); i++) { final String pkg = (String) Main.SKIP.get(i); if (name.equals(pkg) || qual.equals(pkg)) { skip = true; break; } } } if (skip) { if (Main.VERBOSE > 0) { System.out.println("Skipping " + c.type().className()); } context.release(info); return; } if (Main.VERBOSE > 0) { System.out.println("Decorating class " + c.type().className()); } if (Main.VERBOSE > 2) { ((ClassFile) info).print(System.out); } final MethodInfo[] methods = c.methods(); // Add residency checks (via transform()) to each method in the class for (int j = 0; j < methods.length; j++) { MethodEditor m; try { m = context.editMethod(methods[j]); } catch (final ClassFormatException ex) { System.err.println(ex.getMessage()); continue; } Main.transform(m); context.commit(methods[j]); } context.commit(info); }
public static void main(String[] args) { ArrayList<Modifier> modifiers = new ArrayList<Modifier>(); modifiers.add(Modifier.ACC_PUBLIC); // ================================================================================ // Create an empty class file // ================================================================================ ClassFile cf = new ClassFile( 49, // Java 1.5 or later new JvmType.Clazz("", "HelloWorld"), // class is HelloWorld JvmTypes.JAVA_LANG_OBJECT, // superclass is Object Collections.EMPTY_LIST, // implements no interfaces modifiers); // which is public // ================================================================================ // Create a static void main(String[]) method // ================================================================================ modifiers = new ArrayList<Modifier>(modifiers); modifiers.add(Modifier.ACC_STATIC); ClassFile.Method method = new ClassFile.Method( "main", // main method new JvmType.Function( // is function JvmTypes.T_VOID, // from void new JvmType.Array(JvmTypes.JAVA_LANG_STRING) // to array of String ), modifiers // which is static public ); cf.methods().add(method); // ================================================================================ // Add bytecodes for printing hello world to method // ================================================================================ ArrayList<Bytecode> bytecodes = new ArrayList<Bytecode>(); bytecodes.add( new Bytecode.GetField( JAVA_LANG_SYSTEM, "out", JAVA_IO_PRINTSTREAM, Bytecode.FieldMode.STATIC)); bytecodes.add(new Bytecode.LoadConst("Hello World")); bytecodes.add( new Bytecode.Invoke( JAVA_IO_PRINTSTREAM, "println", new JvmType.Function(JvmTypes.T_VOID, JvmTypes.JAVA_LANG_STRING), Bytecode.InvokeMode.VIRTUAL)); bytecodes.add(new Bytecode.Return(null)); method.attributes().add(new Code(bytecodes, Collections.EMPTY_LIST, method)); // ================================================================================ // Finally, write the class file to disk // ================================================================================ try { FileOutputStream fos = new FileOutputStream("HelloWorld.class"); ClassFileWriter cfw = new ClassFileWriter(fos); cfw.write(cf); } catch (IOException e) { System.out.println("I/O error --- " + e.getMessage()); } }