📄 classreader.java
字号:
/* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.jvm;import java.io.*;import java.net.URI;import java.nio.CharBuffer;import java.util.EnumSet;import java.util.HashMap;import java.util.Map;import java.util.Set;import javax.lang.model.SourceVersion;import javax.tools.JavaFileObject;import javax.tools.JavaFileManager;import javax.tools.StandardJavaFileManager;import com.sun.tools.javac.comp.Annotate;import com.sun.tools.javac.code.*;import com.sun.tools.javac.code.Type.*;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.code.Symtab;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.List;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;import com.sun.tools.javac.jvm.ClassFile.NameAndType;import javax.tools.JavaFileManager.Location;import static javax.tools.StandardLocation.*;/** 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. * * <p><b>This is NOT part of any API supported by Sun Microsystems. If * you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class ClassReader extends ClassFile implements Completer { /** The context key for the class reader. */ protected static final Context.Key<ClassReader> classReaderKey = new Context.Key<ClassReader>(); Annotate annotate; /** Switch: verbose output. */ boolean verbose; /** Switch: check class file for correct minor version, unrecognized * attributes. */ 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; /** Switch: read GJ signature information. */ boolean allowGenerics; /** Switch: read varargs attribute. */ boolean allowVarargs; /** Switch: allow annotations. */ boolean allowAnnotations; /** Switch: preserve parameter names from the variable table. */ public boolean saveParameterNames; /** * Switch: cache completion failures unless -XDdev is used */ private boolean cacheCompletionFailure; /** * Switch: prefer source files instead of newer when both source * and class are available **/ public boolean preferSource; /** The log to use for verbose output */ final Log log; /** The symbol table. */ Symtab syms; Types types; /** The name table. */ final Name.Table names; /** Force a completion failure on this name */ final Name completionFailureName; /** Access to files */ private final JavaFileManager fileManager; /** 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 Map<Name,ClassSymbol> classes; /** A hashtable containing the encountered packages. */ private Map<Name, PackageSymbol> packages; /** The current scope where type variables are entered. */ protected Scope typevars; /** The path name of the class file currently being read. */ protected JavaFileObject currentClassFile = null; /** The class or method currently being read. */ protected Symbol currentOwner = null; /** The buffer containing the currently read class file. */ byte[] buf = new byte[0x0fff0]; /** 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 = 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 HashMap<Name, PackageSymbol>(); classes = new HashMap<Name, ClassSymbol>(); } packages.put(names.empty, syms.rootPackage); syms.rootPackage.completer = this; syms.unnamedPackage.completer = this; } /** Construct a new class reader, optionally treated as the * definitive classreader for this invocation. */ protected ClassReader(Context context, boolean definitive) { if (definitive) context.put(classReaderKey, this); names = Name.Table.instance(context); syms = Symtab.instance(context); types = Types.instance(context); fileManager = context.get(JavaFileManager.class); if (fileManager == null) throw new AssertionError("FileManager initialization error"); init(syms, definitive); log = Log.instance(context); Options options = Options.instance(context); annotate = Annotate.instance(context); verbose = options.get("-verbose") != null; checkClassFile = options.get("-checkclassfile") != null; Source source = Source.instance(context); allowGenerics = source.allowGenerics(); allowVarargs = source.allowVarargs(); allowAnnotations = source.allowAnnotations(); saveParameterNames = options.get("save-parameter-names") != null; cacheCompletionFailure = options.get("dev") == null; preferSource = "source".equals(options.get("-Xprefer")); completionFailureName = (options.get("failcomplete") != null) ? names.fromString(options.get("failcomplete")) : null; typevars = new Scope(syms.noSymbol); } /** Add member to class unless it is synthetic. */ private void enterMember(ClassSymbol c, Symbol sym) { if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC) c.members_field.enter(sym); }/************************************************************************ * Error Diagnoses ***********************************************************************/ public static class BadClassFile extends CompletionFailure { private static final long serialVersionUID = 0; /** * @param msg A localized message. */ public BadClassFile(ClassSymbol c, Object cname, Object msg) { super(c, Log.getLocalizedString("bad.class.file.header", cname, msg)); } } public BadClassFile badClassFile(String key, Object... args) { return new BadClassFile ( currentOwner.enclClass(), currentClassFile, Log.getLocalizedString(key, args)); }/************************************************************************ * Buffer Access ***********************************************************************/ /** Read a character. */ char nextChar() { return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF)); } /** Read an integer. */ int nextInt() { return ((buf[bp++] & 0xFF) << 24) + ((buf[bp++] & 0xFF) << 16) + ((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF); } /** Extract a character at position bp from buf. */ char getChar(int bp) { return (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF)); } /** Extract an integer at position bp from buf. */ int getInt(int bp) { return ((buf[bp] & 0xFF) << 24) + ((buf[bp+1] & 0xFF) << 16) + ((buf[bp+2] & 0xFF) << 8) + (buf[bp+3] & 0xFF); } /** 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(e); } } /** 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(e); } } /** 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(e); } }/************************************************************************ * Constant Pool Access ***********************************************************************/ /** Index all constant pool entries, writing their start addresses into * poolIdx. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -