javacodecompact.java
来自「This is a resource based on j2me embedde」· Java 代码 · 共 1,056 行 · 第 1/3 页
JAVA
1,056 行
return true; } else { return false; } } /** * Do closure on CP entry class constant references until no unresolved * constants remain. * NOTE: doClosure() only loads ClassInfos for each class that is * referenced from unresolved CP entries. After doClosure() is done * (assuming full transitive closure is desired), then all the CP * entries for class constants will reference a ClassInfo object. * NOTE: resolving CP entry class constants to ClassInfo does not * include quickening of bytecodes and other types of VM specific * processing associated with resolution yet. That part is done * later. */ private boolean doClosure() { // do closure on references until none remain. while (true) { Assert.disallowClassloading(); Set undefinedClassNames = findUnresolvedClassNames(classesProcessed.elements()); String unresolved[] = unresolvedClassNames(undefinedClassNames); Assert.allowClassloading(); if (unresolved == null) break; // none left! int nfound = 0; Vector processedThisTime = new Vector(); for( int i=0; i < unresolved.length; i++){ try { Vector oneClass = new Vector(); loadClass(ClassTable.getClassLoader(), unresolved[i], oneClass); processedThisTime.addAll(oneClass); } catch (Exception e) { return false; } } // If we have gone through an iteration when we weren't able to // resolve any more classes, then we have resolved everything // we can. Hence, break out of here. if (processedThisTime.isEmpty()) { break; } // Otherwise, continue to resolve the new classes that we've found. classesProcessed.addAll(processedThisTime); } return true; } /** * Performs the work for JCC. This is the root processing method in JCC * which in turn will call all other processing methods. * NOTE: process() is responsible for resolving all the constant pool * entries of the loaded classes if possible. If full transitive closure * is required, then this is the place where the work will be done. * * @return false if an error was discovered. */ private boolean process(boolean doWrite) throws Exception { /* Do closure on references until none remain. * NOTE: doClosure() only loads ClassInfos for each class that is * referenced from unresolved CP entries. After doClosure() is done * (assuming full transitive closure is desired), then all the CP * entries for class constants will reference a ClassInfo object. * NOTE: resolving CP entry class constants to ClassInfo does not * include quickening of bytecodes and other types of VM specific * processing associated with resolution yet. That part is done * later. */ if (!doClosure()) { return false; } ClassInfo c[] = ClassTable.allClasses(); nclasses = c.length; if (verbosity != 0) System.out.println(Localizer.getString( "javacodecompact.resolving_superclass_hierarchy") ); if (! ClassInfo.resolveSupers()){ return false; // missing superclass is a fatal error. } for (int i = 0; i < nclasses; i++){ ClassInfo cinfo = c[i]; if (!(cinfo instanceof PrimitiveClassInfo) && !(cinfo instanceof ArrayClassInfo)) { if (verbosity != 0) System.out.println(Localizer.getString( "javacodecompact.building_tables_for_class", cinfo.className)); cinfo.buildFieldtable(); cinfo.buildMethodtable(); } } // Warn if fields or methods marked for exclusion were not found checkExcludedClassEntries(); if (!doWrite) { return true; } // now write the output if (verbosity != 0) System.out.println(Localizer.getString( "javacodecompact.writing_output_file")); writeNativeHeaders( nativeTypes, c, nclasses ); writeNativeHeaders( extraHeaders, c, nclasses ); if (stubDestName != null){ writeCStubs( c, nclasses ); } boolean good = true; if (firstTimeOnly) { // For CVM, make sure that all arrays of basic types // are instantiated! good = instantiateBasicArrayClasses(verbosity > 1); firstTimeOnly = false; } // prepareClasses() is responsible for quickening bytecodes, // optimizing the bytecode, constantpools, etc. This is where // CP resolution as the VM knows it is done. if (!prepareClasses(c) || !good) { return false; } if (doWrite) { makeOutfileName(); } good = writeROMFile( outName, c, romAttributes, doWrite ); /* Don't destroy class vector. The JavaAPILister * needs to access class typeids, which come * from CVMClass and CVMClass come from the class * vector. */ //ClassClass.destroyClassVector(); return good; } public static void main( String clist[] ){ boolean success = false; try { try { JavaCodeCompact jcc = new JavaCodeCompact(); // Parse the command line arguments and check for malformed // arguments or a file read error? // Note that processOptions also loads all the initial // classes to be romized specified at the JCC command line. // These classes will be loaded, but their constant pool // entries wil not be resolved yet. if (jcc.processOptions(clist)) { // If we got here, then the arguments were parsed // successfully. Now, we are ready to do some // additional work. This includes resolving the // constant pool entries, quickening bytecodes, etc. success = jcc.process(true); } /* We are done with processing ROMized classes. Now run * JavaAPILister, which need to access some of the data * such as class and member typeid that we created during * Romizing classes. */ if (APIListerArgs != null) { new JavaAPILister().process(APIListerArgs); } }finally{ System.out.flush(); System.err.flush(); } }catch (Throwable t){ t.printStackTrace(); } if (!success){ // process threw error or failed System.exit(1); } return; } /* * ALL THIS IS FOR ROMIZATION */ public boolean instantiateBasicArrayClasses(boolean verbose) { boolean good = true; // For CVM, make sure that all arrays of basic types // are instantiated! String basicArray[] = { "[C", "[S", "[Z", "[I", "[J", "[F", "[D", "[B", "[Ljava/lang/Object;" // not strictly basic. }; for ( int ino = 0; ino < basicArray.length; ino++ ){ if (!ArrayClassInfo.collectArrayClass(basicArray[ino], verbose)) { good = false; } } return good; } /* * Iterate through all known classes. * Iterate through all constant pools. * Look at ClassConstants. If they are unbound, * and if they are references to array classes, * then instantiate the classes and rebind. */ public boolean instantiateArrayClasses( ClassInfo classTable[], boolean verbose) { int nclasses = classTable.length; boolean good = true; // Now dredge through all class constant pools. for ( int cno = 0; cno < nclasses; cno++ ){ ClassInfo c = classTable[cno]; ConstantObject ctable[] = c.getConstantPool().getConstants(); if ( ctable == null ) continue; int n = ctable.length; for( int i = 1; i < n; i++ ){ if ( ctable[i] instanceof ClassConstant ){ ClassConstant cc = (ClassConstant)ctable[i]; String cname = cc.name.string; if (cname.charAt(0) != Const.SIGC_ARRAY ){ continue; // not interesting } if (cc.isResolved()){ continue; // not interesting } if (!vm.ArrayClassInfo.collectArrayClass(cname, verbose)) { good = false; } cc.forget(); // forget the fact that we couldn't find it } } // We might just want to check the code as well. for (int j = 0; j < c.methods.length; j++) { MethodInfo m = c.methods[j]; m.collectArrayForAnewarray(ctable, c.className); } } return good; } /* * We attempt to factor out VM specific code * by subclassing ClassClass. Perhaps we should be subclassing * components.ClassInfo itself. * Anyway, this is the CVM-specific class factory. This * would better be dependent on a runtime switch. */ VMClassFactory classMaker = new CVMClassFactory(); public ClassClass[] finalizeClasses() throws Exception{ ClassClass classes[] = ClassClass.getClassVector(classMaker); int numberOfClasses = classes.length; CodeHacker ch = new CodeHacker( qlossless, jitOn, verbosity >= 2 ); for (int i = 0; i < numberOfClasses; i++) { if (verbosity != 0) { System.out.println(Localizer.getString( "javacodecompact.quickening_code_of_class", classes[i].classInfo.className)); } if (!ch.quickenAllMethodsInClass(classes[i].classInfo)) { throw new Exception(Localizer.getString( "javacodecompact.quickening_code_of_class", classes[i].classInfo.className)); } } // constant pool smashing has to be done after quickening, // else it doesn't make much difference! for (int i = 0; i < numberOfClasses; i++) { ClassInfo cinfo = classes[i].classInfo; if (verbosity != 0) { System.out.println(Localizer.getString( "javacodecompact.reducing_constant_pool_of_class", cinfo.className)); } cinfo.countReferences(false); cinfo.smashConstantPool(); cinfo.relocateReferences(); } /* * This last-minute preparation step might be generalized * to something more useful. */ if (!noCodeCompaction && !qlossless) { for (int i = 0; i < numberOfClasses; i++) { classes[i].getInlining(); } } return classes; } private void validateClasses(ClassClass classes[], ConstantPool sharedConstant){ int totalclasses = classes.length; for (int i = 0; i < totalclasses; i++){ ClassInfo ci = classes[i].classInfo; ci.validate(sharedConstant); } } ConstantPool sharedConstant = null; private boolean prepareClasses(ClassInfo classTable[]) throws Exception { UnresolvedReferenceList missingObjects = new UnresolvedReferenceList(); boolean anyMissingConstants = false; boolean good = instantiateArrayClasses( classTable, verbosity>1 ); // is better to have this after instantiating Array classes, I think. ClassClass classes[] = finalizeClasses(); int totalclasses = classes.length; // at this point, the classes array INCLUDES all the array // classes. classTable doesn't include these! // Since array classes CANNOT participate in sharing // (because of magic offsets) they are excluded from the // sharing calculation below. And because they don't have // any code... if (useSharedCP) { // create a shared constant pool sharedConstant = new ConstantPool(); for (int i = 0; i < classTable.length; i++) mergeConstantsIntoSharedPool(classTable[i], sharedConstant); // sort the reference count sharedConstant.doSort(); // run via the shared constant pool once. if (ClassClass.isPartiallyResolved(sharedConstant)) { sharedConstant = classMaker.makeResolvable( sharedConstant, missingObjects, "shared constant pool");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?