📄 methodinfo.java
字号:
/* * @(#)MethodInfo.java 1.51 06/10/22 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program 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. * * This program 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 at /legal/license.txt). * * 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 or visit www.sun.com if you need additional * information or have any questions. * */package components;import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import java.io.PrintWriter;import java.io.StringWriter;import java.util.Hashtable;import java.util.Vector;import consts.Const;import consts.CVMConst;import jcc.Util;import util.DataFormatException;import util.ValidationException;/* * Class for representing every method in a class * As with ClassInfo, this represents the VM-independent information * (except that it seems to know a lot about quickening!) * The truely VM-specific information is in the VMMethodInfo and its * subclass the CVMMethodInfo. See field vmMethodInfo below. */publicclass MethodInfo extends ClassMemberInfo implements Const, Cloneable{ public int argsSize; public int stack; public int locals; public int methodTableIndex = -1; public byte code[]; private Attribute methodAttributes[]; public CodeAttribute codeAttribute; public Attribute codeAttributes[]; public ExceptionEntry exceptionTable[]; public ClassConstant exceptionsThrown[]; private boolean checkedDebugTables = false; private LineNumberTableEntry lineNumberTable[]; private LocalVariableTableEntry localVariableTable[]; public vm.VMMethodInfo vmMethodInfo; /* An array of the methods called by invokevirtual_quick and * invokevirtualobject_quick. (After quickening, before inlining). */ public MethodInfo[] targetMethods; /** * The following are arrays of indexes into the * code array of references to the constant pool: * ldcInstructions lists the instructions with a one-byte index. * wideConstantRefInstructions lists the instructions with a two-byte index. * In each case, the index is that of the opcode: the actual reference * begins with the following byte. * Entries of value -1 are ignored. */ private int ldcInstructions[]; private int wideConstantRefInstructions[]; public boolean hasCheckinits = false; // Keep track of any list of methods to be excluded during // processing. Initialize once and then remove each entry, // if there are any, as it is found. static private Vector excludeList = null; static void setExcludeList( Vector v ) { excludeList = v; return; } protected Object clone() throws CloneNotSupportedException{ MethodInfo m = (MethodInfo)super.clone(); return m; } public MethodInfo( int name, int sig, int access, ClassInfo p ) { super( name, sig, access, p ); } public void initializeClassDebugTables() { int nattr = (codeAttributes == null) ? 0 : codeAttributes.length; // parse code attributes for (int i = 0; i < nattr; i++) { Attribute a = codeAttributes[i]; if (a.name.string.equals("LineNumberTable")) { lineNumberTable = ((LineNumberTableAttribute)a).data; } if (a.name.string.equals("LocalVariableTable")) { localVariableTable = ((LocalVariableTableAttribute)a).data; } } } public LineNumberTableEntry [] getLineNumberTable(){ if ( !checkedDebugTables ){ initializeClassDebugTables(); checkedDebugTables = true; } return lineNumberTable; } public LocalVariableTableEntry [] getLocalVariableTable(){ if ( !checkedDebugTables ){ initializeClassDebugTables(); checkedDebugTables = true; } return localVariableTable; } public boolean hasLineNumberTable(){ if ( !checkedDebugTables ){ initializeClassDebugTables(); checkedDebugTables = true; } return (lineNumberTable != null) && (lineNumberTable.length != 0); } public boolean hasLocalVariableTable(){ if ( !checkedDebugTables ){ initializeClassDebugTables(); checkedDebugTables = true; } return (localVariableTable != null) && (localVariableTable.length != 0); } public boolean throwsExceptions(){ return exceptionsThrown != null; } public ClassConstant[] getExceptionsThrown(){ return exceptionsThrown; } public int nExceptionsThrown(){ return ( exceptionsThrown == null ) ? 0 : exceptionsThrown.length; } private String nativeName; public String getNativeName(boolean isJNI) { if (nativeName == null) { nativeName = isJNI ? getJNIName() : getOldNativeName(); } return nativeName; } public boolean isNonTrivial() { // // We can only tell if a method is trivial or not by looking // at its bytecodes. Otherwise we assume non-trivial. // if (code != null) { if ((code.length == 1) && (code[0] == (byte)opc_return)) { return false; } } return true; } private String getJNIName() { ClassInfo ci = parent; String classname = ci.className; String methodname = this.name.string; int nmethods = ci.methods.length; String typeName = null; // by default, don't need type for (int j = 0; j < nmethods; j ++ ){ MethodInfo m = ci.methods[j]; if ((m != this) && ( (m.access&Const.ACC_NATIVE) != 0 )) { if (m.name.equals(this.name)) { // Two native methods with the same name. Need type name typeName = this.type.string; break; } } } return Util.convertToJNIName(classname, methodname, typeName); } private String getOldNativeName() { ClassInfo ci = parent; String methodname = this.name.string; StringBuffer sbuf = new StringBuffer(/*NOI18N*/"Java_") .append(ci.getGenericNativeName()) .append('_'); if (methodname.indexOf('_') == -1) { // optimization. Most methods don't have an _ in them sbuf.append(methodname); } else { for (int i = 0; i < methodname.length(); i++) { if (methodname.charAt(i) == '_') { sbuf.append(/*NOI18N*/"_0005f"); } else { sbuf.append(methodname.charAt(i)); } } } sbuf.append("_stub"); return sbuf.toString(); } /* * A methods attributes are Code and Exceptions. */ private static Hashtable methodAttributeTypes = new Hashtable(); static { methodAttributeTypes.put( "Code", CodeAttributeFactory.instance ); methodAttributeTypes.put( "Exceptions", ExceptionsAttributeFactory.instance ); } // Read in method attributes from classfile void readAttributes(DataInput in, ConstantPool cp, boolean readCode) throws IOException { methodAttributes = Attribute.readAttributes(in, cp, methodAttributeTypes, false); // NOTE: The above reads in the code as well. We might want to // optimize this. // // parse special attributes // if (methodAttributes != null) { for (int i = 0; i < methodAttributes.length; i++) { Attribute a = methodAttributes[i]; if (a.name.string.equals("Code")) { CodeAttribute ca = (CodeAttribute)a; this.locals = ca.locals; this.stack = ca.stack; this.code = ca.code; this.exceptionTable = ca.exceptionTable; this.codeAttributes = ca.codeAttributes; this.codeAttribute = ca; } else if (a.name.string.equals("Exceptions") ) { this.exceptionsThrown = ((ExceptionsAttribute)a).data; } } } } public static MethodInfo readMethod( DataInput in, ClassInfo p, boolean readCode ) throws IOException { int access = in.readUnsignedShort(); int name = in.readUnsignedShort(); int sig = in.readUnsignedShort(); MethodInfo m = new MethodInfo( name, sig, access, p ); // the bad thing is, we really cannot go far // without resolving. So we resolve here. ConstantPool cp = p.getConstantPool(); m.flatten(cp); m.argsSize = Util.argsSize(m.type.string); if ((m.access & ACC_STATIC) == 0) { m.argsSize++; } m.readAttributes(in, cp, readCode); ConstantObject[] constants = cp.getConstants(); // Check to make sure this method isn't marked for exclusion if (excludeList != null && excludeList.size() > 0) { // See if this method is to be discarded. The vector holds // the signature of methods to be excluded parsed into // class, method & type portions. for (int i = 0 ; i < excludeList.size() ; i++) { String paramlist = constants[sig].toString(); paramlist = paramlist.substring(0, paramlist.indexOf(')')+1); MemberNameTriple t = (MemberNameTriple)excludeList.elementAt(i); if (t.sameMember(p.className, constants[name].toString(), paramlist)) { excludeList.remove(i); return (MethodInfo)null; } } } return m; } public void write( DataOutput o ) throws IOException{ o.writeShort( access ); o.writeShort( name.index ); o.writeShort( type.index ); Attribute.writeAttributes( methodAttributes, o, false ); } public int getInt( int w ){ return ( (int)code[w] << 24 ) | (( (int)code[w+1] &0xff ) << 16 ) | (( (int)code[w+2] &0xff ) << 8 ) | ( (int)code[w+3] &0xff ); } public int getUnsignedShort( int w ){ return (( (int)code[w] &0xff ) << 8 ) | ( (int)code[w+1] &0xff ); } public int getShort( int w ){ return (( (int)code[w]) << 8 ) | ( (int)code[w+1] &0xff ); } // // Private Utility functions private void putInt(byte array[], int offset, int val) { array[offset] = (byte) ((val >> 24) & 0xFF); array[offset+1] = (byte) ((val >> 16) & 0xFF); array[offset+2] = (byte) ((val >> 8) & 0xFF); array[offset+3] = (byte) (val & 0xFF); } private void putShort( int w, short v ){ code[w] = (byte)(v>>>8); code[w+1] = (byte)v; } private void findConstantReferences() throws DataFormatException { if ( code == null ) return; // no code, no references. int ldc[] = new int[ code.length / 2 ]; int wide[] = new int[ code.length / 3 ]; int nldc = 0; int nwide = 0; int ncode = code.length; int opcode; for( int i = 0; i < ncode; /*nothing*/){ switch (opcode = (int)code[i]&0xff) { case opc_tableswitch: i = (i + 4) & ~3; int low = getInt( i+4); int high = getInt( i+8); i += (high - low + 1) * 4 + 12; break; case opc_lookupswitch: i = (i + 4) & ~3; int pairs = getInt(i+4); i += pairs * 8 + 8; break; case opc_wide: switch ((int)code[i+1]&0xff) { case opc_aload: case opc_iload: case opc_fload: case opc_lload: case opc_dload: case opc_istore: case opc_astore: case opc_fstore: case opc_lstore: case opc_dstore: case opc_ret: i += 4; break; case opc_iinc: i += 6; break; default: throw new DataFormatException( parent.className + "." + name.string + ": unknown wide " + "instruction: " + code[i+1] ); } break; case opc_ldc: case opc_ldc_quick: case opc_aldc_quick: case opc_aldc_ind_quick: ldc[nldc++] = i; i += opcLengths[opcode]; break; case opc_ldc_w: case opc_ldc2_w: case opc_getstatic: case opc_putstatic: case opc_getfield: case opc_putfield: case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: case opc_invokeinterface: case opc_new: case opc_anewarray: case opc_checkcast: case opc_instanceof: case opc_multianewarray: case opc_ldc_w_quick: case opc_aldc_w_quick: case opc_aldc_ind_w_quick: case opc_ldc2_w_quick: case opc_getstatic_quick: case opc_putstatic_quick: case opc_agetstatic_quick: case opc_aputstatic_quick:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -