📄 classreader.java
字号:
/** * @(#)ClassReader.java 1.55 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.tools.javac.v8.code;import com.sun.tools.javac.v8.util.*;import java.io.*;import java.util.zip.*;import java.util.StringTokenizer;import com.sun.tools.javac.v8.code.Type.*;import com.sun.tools.javac.v8.code.Symbol.*;import com.sun.tools.javac.v8.code.Symtab;/** * This class provides operations to read a classfile into an internal * representation. The internal representation is anchored in a * ClassSymbol which contains in its scope symbol representations * for all other definitions in the classfile. Top-level Classes themselves * appear as members of the scopes of PackageSymbols. */public class ClassReader extends ClassFile implements Completer, Flags, Kinds,TypeTags { /** * The context key for the class reader. */ private static final Context.Key classReaderKey = new Context.Key(); /** * The string used as separator in class paths. */ public static final String pathSep = System.getProperty("path.separator"); /** * Switch: verbose output. */ public boolean verbose; /** * Switch: check class file for correct minor version, unrecognized * attributes. */ public boolean checkClassFile; /** * Switch: read constant pool and code sections. This switch is initially * set to false but can be turned on from outside. */ public boolean readAllOfClassFile = false; /** * The log to use for verbose output */ private final Log log; /** * The symbol table. */ private final Symtab syms; /** * The name table. */ protected final Name.Table names; /** * Force a completion failure on this name */ final Name completionFailureName; /** * Can be reassigned from outside: * the class path to be searched for user classes. */ public String classPath; /** * The class path to be searched for system classes. */ public String bootClassPath; /** * The path to be searched for sources */ public String sourceClassPath; /** * Can be reassigned from outside: * the completer to be used for ".java" files. If this remains unassigned * ".java" files will not be loaded. */ public SourceCompleter sourceCompleter = null; /** * A hashtable containing the encountered top-level and member classes, * indexed by flat names. The table does not contain local classes. */ private Hashtable classes; /** * A hashtable containing the encountered packages. */ private Hashtable packages; /** * The current scope where type variables are entered. */ Scope typevars = new Scope(null); /** * The path name of the class file currently being read. */ String currentClassFileName = null; /** * The class or method currently being read. */ Symbol currentOwner = null; /** * The buffer containing the currently read class file. */ byte[] buf = new byte[65520]; /** * The current input pointer. */ int bp; /** * The objects of the constant pool. */ Object[] poolObj; /** * For every constant pool entry, an index into buf where the * defining section of the entry is found. */ int[] poolIdx; /** * Get the ClassReader instance for this invocation. */ public static ClassReader instance(Context context) { ClassReader instance = (ClassReader) context.get(classReaderKey); if (instance == null) instance = new ClassReader(context, true); return instance; } /** * Initialize classes and packages, treating this as the definitive classreader. */ public void init(Symtab syms) { init(syms, true); } /** * Initialize classes and packages, optionally treating this as * the definitive classreader. */ private void init(Symtab syms, boolean definitive) { if (classes != null) return; if (definitive) { assert packages == null || packages == syms.packages; packages = syms.packages; assert classes == null || classes == syms.classes; classes = syms.classes; } else { packages = new Hashtable(); classes = new Hashtable(); } packages.put(syms.rootPackage.fullname, syms.rootPackage); syms.rootPackage.completer = this; packages.put(syms.emptyPackage.fullname, syms.emptyPackage); syms.emptyPackage.completer = this; } /** * Construct a new class reader, optionally treated as the * definitive classreader for this invocation. */ protected ClassReader(Context context, boolean definitive) { super(); if (definitive) context.put(classReaderKey, this); names = Name.Table.instance(context); syms = Symtab.instance(context); init(syms, definitive); log = Log.instance(context); Options options = Options.instance(context); verbose = options.get("-verbose") != null; checkClassFile = options.get("-checkclassfile") != null; setClassPaths(options); completionFailureName = (options.get("failcomplete") != null) ? names.fromString((String) options.get("failcomplete")) : null; } /** * Set classPath, bootClassPath, and sourceClassPath. */ private void setClassPaths(Options options) { String cp = (String) options.get("-classpath"); if (cp == null) cp = System.getProperty("env.class.path"); if (cp == null && System.getProperty("application.home") == null) cp = System.getProperty("java.class.path"); if (cp == null) cp = "."; classPath = terminate(cp); String bp = (String) options.get("-bootclasspath"); if (bp == null) { bp = System.getProperty("sun.boot.class.path"); if (bp == null) bp = System.getProperty("java.class.path"); if (bp == null) bp = "."; } String bpp = (String) options.get("-Xbootclasspath/p:"); if (bpp != null) bp = bpp + System.getProperty("path.separator") + bp; bootClassPath = terminate(bp); String ed = (String) options.get("-extdirs"); if (ed == null) ed = System.getProperty("java.ext.dirs"); if (ed == null) ed = ""; String extdirs = terminate(ed); int i = 0; int edlen = extdirs.length(); while (i < edlen) { int end = extdirs.indexOf(pathSep, i); String extdir = extdirs.substring(i, end); addArchives(extdir); i = end + 1; } String sp = (String) options.get("-sourcepath"); if (sp != null) { sourceClassPath = terminate(sp); } else { sourceClassPath = null; } } /** * Add all archives in `extdir' to boot class path */ private void addArchives(String extdir) { String[] archives = new File(extdir).list(); for (int i = 0; archives != null && i < archives.length; i++) { if (archives[i].endsWith(".jar")) { String prefix = (extdir.endsWith(File.separator)) ? extdir : (extdir + File.separator); bootClassPath = bootClassPath + prefix + archives[i] + pathSep; } } } /** * Add path separator to string if it does not end in one already */ private String terminate(String s) { return (s.endsWith(pathSep)) ? s : s + pathSep; } /** * Add member to class unless it is synthetic */ private void enterMember(ClassSymbol c, Symbol sym) { if ((sym.flags_field & SYNTHETIC) == 0) c.members_field.enter(sym); } /** * Error Diagnoses */ public static class BadClassFile extends CompletionFailure { /** * @param msg A localized message. */ public BadClassFile(ClassSymbol c, String cname, String msg) { super(c, Log.getLocalizedString("bad.class.file.header", cname, msg)); } } public BadClassFile badClassFile(String key) { return new BadClassFile(currentOwner.enclClass(), currentClassFileName, Log.getLocalizedString(key)); } public BadClassFile badClassFile(String key, String arg0) { return new BadClassFile(currentOwner.enclClass(), currentClassFileName, Log.getLocalizedString(key, arg0)); } public BadClassFile badClassFile(String key, String arg0, String arg1) { return new BadClassFile(currentOwner.enclClass(), currentClassFileName, Log.getLocalizedString(key, arg0, arg1)); } public BadClassFile badClassFile(String key, String arg0, String arg1, String arg2) { return new BadClassFile(currentOwner.enclClass(), currentClassFileName, Log.getLocalizedString(key, arg0, arg1, arg2)); } public BadClassFile badClassFile(String key, String arg0, String arg1, String arg2, String arg3) { return new BadClassFile(currentOwner.enclClass(), currentClassFileName, Log.getLocalizedString(key, arg0, arg1, arg2, arg3)); } /** * Read a character. */ char nextChar() { return (char)(((buf[bp++] & 255)<< 8) + (buf[bp++] & 255)); } /** * Read an integer. */ int nextInt() { return ((buf[bp++] & 255)<< 24) + ((buf[bp++] & 255)<< 16) + ((buf[bp++] & 255)<< 8) + (buf[bp++] & 255); } /** * Extract a character at position bp from buf. */ char getChar(int bp) { return (char)(((buf[bp] & 255)<< 8) + (buf[bp + 1] & 255)); } /** * Extract an integer at position bp from buf. */ int getInt(int bp) { return ((buf[bp] & 255)<< 24) + ((buf[bp + 1] & 255)<< 16) + ((buf[bp + 2] & 255)<< 8) + (buf[bp + 3] & 255); } /** * Extract a long integer at position bp from buf. */ long getLong(int bp) { DataInputStream bufin = new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); try { return bufin.readLong(); } catch (IOException e) { throw new AssertionError(); } } /** * Extract a float at position bp from buf. */ float getFloat(int bp) { DataInputStream bufin = new DataInputStream(new ByteArrayInputStream(buf, bp, 4)); try { return bufin.readFloat(); } catch (IOException e) { throw new AssertionError(); } } /** * Extract a double at position bp from buf. */ double getDouble(int bp) { DataInputStream bufin = new DataInputStream(new ByteArrayInputStream(buf, bp, 8)); try { return bufin.readDouble(); } catch (IOException e) { throw new AssertionError(); } } /** * Index all constant pool entries, writing their start addresses into * poolIdx. */ void indexPool() { poolIdx = new int[nextChar()]; poolObj = new Object[poolIdx.length]; int i = 1; while (i < poolIdx.length) { poolIdx[i++] = bp; byte tag = buf[bp++]; switch (tag) { case CONSTANT_Utf8: case CONSTANT_Unicode: { int len = nextChar(); bp = bp + len; break; } case CONSTANT_Class: case CONSTANT_String: bp = bp + 2; break; case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: case CONSTANT_NameandType: case CONSTANT_Integer: case CONSTANT_Float: bp = bp + 4; break; case CONSTANT_Long: case CONSTANT_Double: bp = bp + 8; i++; break; default: throw badClassFile("bad.const.pool.tag.at", Byte.toString(tag), Integer.toString(bp - 1)); } } } /** * Read constant pool entry at start address i, use pool as a cache. */ Object readPool(int i) { Object result = poolObj[i]; if (result != null) return result; int index = poolIdx[i]; if (index == 0) return null; byte tag = buf[index]; switch (tag) { case CONSTANT_Utf8: poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1)); break; case CONSTANT_Unicode:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -