ClosureFinder.java revision 0
0N/A * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 0N/A * published by the Free Software Foundation. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 0N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 0N/A * CA 95054 USA or visit www.sun.com if you need additional information or 0N/A * have any questions. 0N/A<p> This class finds transitive closure of dependencies from a given 0N/Aroot set of classes. If your project has lots of .class files and you 0N/Awant to ship only those .class files which are used (transitively) 0N/Afrom a root set of classes, then you can use this utility. </p> <p> 0N/AHow does it work?</p> 0N/A<p> We walk through all constant pool entries of a given class and 0N/Afind all modified UTF-8 entries. Anything that looks like a class name is 0N/Aconsidered as a class and we search for that class in the given 0N/Aclasspath. If we find a .class of that name, then we add that class to 0N/A<p> We could have used CONSTANT_ClassInfo type constants only. But 0N/Athat will miss classes used through Class.forName or xyz.class 0N/Aconstruct. But, if you refer to a class name in some other string we 0N/Awould include it as dependency :(. But this is quite unlikely 0N/Aanyway. To look for exact Class.forName argument(s) would involve 0N/Abytecode analysis. Also, we handle only simple reflection. If you 0N/Aaccept name of a class from externally (for eg properties file or 0N/Acommand line args for example, this utility will not be able to find 0N/Athat dependency. In such cases, include those classes in the root set. 0N/A // parse classPath into pathComponents array 0N/A // if output is aleady not computed, compute it now 0N/A // result is a map from class file name to base path where the .class was found 0N/A // compute closure for all given root classes 0N/A // looks up for .class in pathComponents and returns 0N/A // base path if found, else returns null 0N/A // Windows reports special devices AUX,NUL,CON as files 0N/A // under any directory. It does not care about file extention :-( 0N/A // from JVM spec. 2'nd edition section 4.4 0N/A // whether a given string may be a class name? 0N/A for (
int s =
0; s <
len; s++) {
0N/A // compute closure for a given class 0N/A // look for .class signature 0N/A // ignore major and minor version numbers 0N/A // read number of constant pool constants 0N/A // zero'th entry is unused 0N/A // all these are 4 byte constants 0N/A // occupies 2 cp entries 0N/A // now walk thru the string constants and look for class names 0N/A // a sample main that accepts roots classes in a file and classpath as args