Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java
41161 views
/*1* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.utilities;2526import java.lang.reflect.Modifier;27import java.util.*;28import java.util.stream.*;29import sun.jvm.hotspot.debugger.*;30import sun.jvm.hotspot.oops.*;31import sun.jvm.hotspot.runtime.*;32import sun.jvm.hotspot.utilities.*;3334/**35* ObjectReader can "deserialize" objects from debuggee.36*37* Class Loading:38*39* ObjectReader loads classes using the given class loader. If no40* class loader is supplied, it uses a ProcImageClassLoader, which41* loads classes from debuggee core or process.4243* Object creation:44*45* This class uses no-arg constructor to construct objects. But if46* there is no no-arg constructor in a given class, then it tries to47* use other constructors with 'default' values - null for object48* types, 0, 0.0, false etc. for primitives. If this process fails to49* construct an instance (because of null checking by constructor or 050* being invalid for an int arg etc.), then null is returned. While51* constructing complete object graph 'null' is inserted silently on52* failure and the deserialization continues to construct best-effort53* object graph.54*55* Debug messages:56*57* The flag sun.jvm.hotspot.utilities.ObjectReader.DEBUG may be set to58* non-null to get debug error messages and stack traces.59*60* JDK version:61*62* JDK classes are loaded by bootstrap class loader and not by the63* supplied class loader or ProcImageClassLoader. This may create64* problems if a JDK class evolves. i.e., if SA runs a JDK version65* different from that of the debuggee, there is a possibility of66* schema change. It is recommended that the matching JDK version be67* used to run SA for proper object deserialization.68*69*/7071public class ObjectReader {7273private static final boolean DEBUG;74static {75DEBUG = System.getProperty("sun.jvm.hotspot.utilities.ObjectReader.DEBUG") != null;76}7778public ObjectReader(ClassLoader cl) {79this.cl = cl;80this.oopToObjMap = new HashMap<>();81this.fieldMap = new HashMap<>();82}8384public ObjectReader() {85this(new ProcImageClassLoader());86}8788static void debugPrintln(String msg) {89if (DEBUG) {90System.err.println("DEBUG>" + msg);91}92}9394static void debugPrintStackTrace(Exception exp) {95if (DEBUG) {96StackTraceElement[] els = exp.getStackTrace();97for (int i = 0; i < els.length; i++) {98System.err.println("DEBUG>" + els[i].toString());99}100}101}102103public Object readObject(Oop oop) throws ClassNotFoundException {104if (oop instanceof Instance) {105return readInstance((Instance) oop);106} else if (oop instanceof TypeArray){107return readPrimitiveArray((TypeArray)oop);108} else if (oop instanceof ObjArray){109return readObjectArray((ObjArray)oop);110} else {111return null;112}113}114115protected final Object getDefaultPrimitiveValue(Class clz) {116if (clz == Boolean.TYPE) {117return Boolean.FALSE;118} else if (clz == Character.TYPE) {119return ' ';120} else if (clz == Byte.TYPE) {121return (byte) 0;122} else if (clz == Short.TYPE) {123return (short) 0;124} else if (clz == Integer.TYPE) {125return 0;126} else if (clz == Long.TYPE) {127return 0L;128} else if (clz == Float.TYPE) {129return 0.0f;130} else if (clz == Double.TYPE) {131return 0.0;132} else {133throw new RuntimeException("should not reach here!");134}135}136137protected String javaLangString;138protected String javaUtilHashtableEntry;139protected String javaUtilHashtable;140protected String javaUtilProperties;141142protected String javaLangString() {143if (javaLangString == null) {144javaLangString = "java/lang/String";145}146return javaLangString;147}148149protected String javaUtilHashtableEntry() {150if (javaUtilHashtableEntry == null) {151javaUtilHashtableEntry = "java/util/Hashtable$Entry";152}153return javaUtilHashtableEntry;154}155156protected String javaUtilHashtable() {157if (javaUtilHashtable == null) {158javaUtilHashtable = "java/util/Hashtable";159}160return javaUtilHashtable;161}162163protected String javaUtilProperties() {164if (javaUtilProperties == null) {165javaUtilProperties = "java/util/Properties";166}167return javaUtilProperties;168}169170private void setHashtableEntry(java.util.Hashtable<Object, Object> p, Oop oop) {171InstanceKlass ik = (InstanceKlass)oop.getKlass();172OopField keyField = (OopField)ik.findField("key", "Ljava/lang/Object;");173OopField valueField = (OopField)ik.findField("value", "Ljava/lang/Object;");174OopField nextField = (OopField)ik.findField("next", "Ljava/util/Hashtable$Entry;");175if (DEBUG) {176if (Assert.ASSERTS_ENABLED) {177Assert.that(ik.getName().equals(javaUtilHashtableEntry()), "Not a Hashtable$Entry?");178Assert.that(keyField != null && valueField != null && nextField != null, "Invalid fields!");179}180}181182Object key = null;183Object value = null;184Oop next = null;185try {186key = readObject(keyField.getValue(oop));187value = readObject(valueField.getValue(oop));188next = (Oop)nextField.getValue(oop);189// For Properties, should use setProperty(k, v). Since it only runs in SA190// using put(k, v) should be OK.191p.put(key, value);192if (next != null) {193setHashtableEntry(p, next);194}195} catch (ClassNotFoundException ce) {196if( DEBUG) {197debugPrintln("Class not found " + ce);198debugPrintStackTrace(ce);199}200}201}202203private void setPropertiesEntry(java.util.Properties p, Oop oop) {204InstanceKlass ik = (InstanceKlass)oop.getKlass();205OopField keyField = (OopField)ik.findField("key", "Ljava/lang/Object;");206OopField valueField = (OopField)ik.findField("val", "Ljava/lang/Object;");207OopField nextField = (OopField)ik.findField("next", "Ljava/util/concurrent/ConcurrentHashMap$Node;");208209try {210p.setProperty((String)readObject(keyField.getValue(oop)),211(String)readObject(valueField.getValue(oop)));212} catch (ClassNotFoundException ce) {213if (DEBUG) {214debugPrintStackTrace(ce);215}216}217// If this hashmap table Node is chained, then follow the chain to the next Node.218Oop chainedOop = nextField.getValue(oop);219if (chainedOop != null) {220setPropertiesEntry(p, chainedOop);221}222}223224protected Object getHashtable(Instance oop) {225InstanceKlass k = (InstanceKlass)oop.getKlass();226OopField tableField = (OopField)k.findField("table", "[Ljava/util/Hashtable$Entry;");227if (tableField == null) {228debugPrintln("Could not find field of [Ljava/util/Hashtable$Entry;");229return null;230}231java.util.Hashtable<Object, Object> table = new java.util.Hashtable<>();232ObjArray kvs = (ObjArray)tableField.getValue(oop);233long size = kvs.getLength();234debugPrintln("Hashtable$Entry Size = " + size);235for (long i=0; i<size; i++) {236Oop entry = kvs.getObjAt(i);237if (entry != null && entry.isInstance()) {238setHashtableEntry(table, entry);239}240}241return table;242}243244private Properties getProperties(Instance oop) {245InstanceKlass k = (InstanceKlass)oop.getKlass();246OopField mapField = (OopField)k.findField("map", "Ljava/util/concurrent/ConcurrentHashMap;");247if (mapField == null) {248debugPrintln("Could not find field of Ljava/util/concurrent/ConcurrentHashMap");249return null;250}251252Instance mapObj = (Instance)mapField.getValue(oop);253if (mapObj == null) {254debugPrintln("Could not get map field from java.util.Properties");255return null;256}257258InstanceKlass mk = (InstanceKlass)mapObj.getKlass();259OopField tableField = (OopField)mk.findField("table", "[Ljava/util/concurrent/ConcurrentHashMap$Node;");260if (tableField == null) {261debugPrintln("Could not find field of [Ljava/util/concurrent/ConcurrentHashMap$Node");262return null;263}264265java.util.Properties props = new java.util.Properties();266ObjArray kvs = (ObjArray)tableField.getValue(mapObj);267long size = kvs.getLength();268debugPrintln("ConcurrentHashMap$Node Size = " + size);269LongStream.range(0, size)270.mapToObj(kvs::getObjAt)271.filter(o -> o != null)272.forEach(o -> setPropertiesEntry(props, o));273274return props;275}276277public Object readInstance(Instance oop) throws ClassNotFoundException {278Object result = getFromObjTable(oop);279if (result == null) {280InstanceKlass kls = (InstanceKlass) oop.getKlass();281// Handle java.lang.String instances differently. As part of JSR-133, fields of immutable282// classes have been made final. The algorithm below will not be able to read Strings from283// debuggee (can't use reflection to set final fields). But, need to read Strings is very284// important.285// Same for Hashtable, key and hash are final, could not be set in the algorithm too.286// FIXME: need a framework to handle many other special cases.287if (kls.getName().equals(javaLangString())) {288return OopUtilities.stringOopToString(oop);289}290291if (kls.getName().equals(javaUtilHashtable())) {292return getHashtable(oop);293}294295if (kls.getName().equals(javaUtilProperties())) {296return getProperties(oop);297}298299Class<?> clz = readClass(kls);300try {301result = clz.getDeclaredConstructor().newInstance();302} catch (Exception ex) {303// no-arg constructor failed to create object. Let us try304// to call constructors one-by-one with default arguments305// (null for objects, 0/0.0 etc. for primitives) till we306// succeed or fail on all constructors.307308java.lang.reflect.Constructor[] ctrs = clz.getDeclaredConstructors();309for (int n = 0; n < ctrs.length; n++) {310java.lang.reflect.Constructor c = ctrs[n];311Class[] paramTypes = c.getParameterTypes();312Object[] params = new Object[paramTypes.length];313for (int i = 0; i < params.length; i++) {314if (paramTypes[i].isPrimitive()) {315params[i] = getDefaultPrimitiveValue(paramTypes[i]);316}317}318try {319c.setAccessible(true);320result = c.newInstance(params);321break;322} catch (Exception exp) {323if (DEBUG) {324debugPrintln("Can't create object using " + c);325debugPrintStackTrace(exp);326}327}328}329}330331if (result != null) {332putIntoObjTable(oop, result);333oop.iterate(new FieldSetter(result), false);334}335}336return result;337}338339public Object readPrimitiveArray(final TypeArray array) {340341Object result = getFromObjTable(array);342if (result == null) {343int length = (int) array.getLength();344TypeArrayKlass klass = (TypeArrayKlass) array.getKlass();345int type = (int) klass.getElementType();346switch (type) {347case TypeArrayKlass.T_BOOLEAN: {348final boolean[] arrayObj = new boolean[length];349array.iterate(new DefaultOopVisitor() {350public void doBoolean(BooleanField field, boolean isVMField) {351IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();352arrayObj[ifd.getIndex()] = field.getValue(array);353}354}, false);355result = arrayObj;356}357break;358359case TypeArrayKlass.T_CHAR: {360final char[] arrayObj = new char[length];361array.iterate(new DefaultOopVisitor() {362public void doChar(CharField field, boolean isVMField) {363IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();364arrayObj[ifd.getIndex()] = field.getValue(array);365}366}, false);367result = arrayObj;368}369break;370371case TypeArrayKlass.T_FLOAT: {372final float[] arrayObj = new float[length];373array.iterate(new DefaultOopVisitor() {374public void doFloat(FloatField field, boolean isVMField) {375IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();376arrayObj[ifd.getIndex()] = field.getValue(array);377}378}, false);379result = arrayObj;380}381break;382383case TypeArrayKlass.T_DOUBLE: {384final double[] arrayObj = new double[length];385array.iterate(new DefaultOopVisitor() {386public void doDouble(DoubleField field, boolean isVMField) {387IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();388arrayObj[ifd.getIndex()] = field.getValue(array);389}390}, false);391result = arrayObj;392}393break;394395case TypeArrayKlass.T_BYTE: {396final byte[] arrayObj = new byte[length];397array.iterate(new DefaultOopVisitor() {398public void doByte(ByteField field, boolean isVMField) {399IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();400arrayObj[ifd.getIndex()] = field.getValue(array);401}402}, false);403result = arrayObj;404}405break;406407case TypeArrayKlass.T_SHORT: {408final short[] arrayObj = new short[length];409array.iterate(new DefaultOopVisitor() {410public void doShort(ShortField field, boolean isVMField) {411IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();412arrayObj[ifd.getIndex()] = field.getValue(array);413}414}, false);415result = arrayObj;416}417break;418419case TypeArrayKlass.T_INT: {420final int[] arrayObj = new int[length];421array.iterate(new DefaultOopVisitor() {422public void doInt(IntField field, boolean isVMField) {423IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();424arrayObj[ifd.getIndex()] = field.getValue(array);425}426}, false);427result = arrayObj;428}429break;430431case TypeArrayKlass.T_LONG: {432final long[] arrayObj = new long[length];433array.iterate(new DefaultOopVisitor() {434public void doLong(LongField field, boolean isVMField) {435IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();436arrayObj[ifd.getIndex()] = field.getValue(array);437}438}, false);439result = arrayObj;440}441break;442443default:444throw new RuntimeException("should not reach here!");445}446447putIntoObjTable(array, result);448}449return result;450}451452protected final boolean isRobust(OopHandle handle) {453return RobustOopDeterminator.oopLooksValid(handle);454}455456public Object readObjectArray(final ObjArray array) throws ClassNotFoundException {457Object result = getFromObjTable(array);458if (result == null) {459int length = (int) array.getLength();460ObjArrayKlass klass = (ObjArrayKlass) array.getKlass();461Klass bottomKls = klass.getBottomKlass();462Class bottomCls = null;463final int dimension = (int) klass.getDimension();464int[] dimArray = null;465if (bottomKls instanceof InstanceKlass) {466bottomCls = readClass((InstanceKlass) bottomKls);467dimArray = new int[dimension];468} else { // instanceof TypeArrayKlass469TypeArrayKlass botKls = (TypeArrayKlass) bottomKls;470dimArray = new int[dimension -1];471}472// initialize the length473dimArray[0] = length;474final Object[] arrayObj = (Object[]) java.lang.reflect.Array.newInstance(bottomCls, dimArray);475putIntoObjTable(array, arrayObj);476result = arrayObj;477array.iterate(new DefaultOopVisitor() {478public void doOop(OopField field, boolean isVMField) {479OopHandle handle = field.getValueAsOopHandle(getObj());480if (! isRobust(handle)) {481return;482}483484IndexableFieldIdentifier ifd = (IndexableFieldIdentifier) field.getID();485try {486arrayObj[ifd.getIndex()] = readObject(field.getValue(getObj()));487} catch (Exception e) {488if (DEBUG) {489debugPrintln("Array element set failed for " + ifd);490debugPrintStackTrace(e);491}492}493}494}, false);495}496return result;497}498499protected class FieldSetter extends DefaultOopVisitor {500protected Object obj;501502public FieldSetter(Object obj) {503this.obj = obj;504}505506private void printFieldSetError(java.lang.reflect.Field f, Exception ex) {507if (DEBUG) {508if (f != null) debugPrintln("Field set failed for " + f);509debugPrintStackTrace(ex);510}511}512513// Callback methods for each field type in an object514public void doOop(OopField field, boolean isVMField) {515OopHandle handle = field.getValueAsOopHandle(getObj());516if (! isRobust(handle) ) {517return;518}519520java.lang.reflect.Field f = null;521try {522f = readField(field);523if (Modifier.isFinal(f.getModifiers())) return;524f.setAccessible(true);525f.set(obj, readObject(field.getValue(getObj())));526} catch (Exception ex) {527printFieldSetError(f, ex);528}529}530531public void doByte(ByteField field, boolean isVMField) {532java.lang.reflect.Field f = null;533try {534f = readField(field);535if (Modifier.isFinal(f.getModifiers())) return;536f.setAccessible(true);537f.setByte(obj, field.getValue(getObj()));538} catch (Exception ex) {539printFieldSetError(f, ex);540}541}542543public void doChar(CharField field, boolean isVMField) {544java.lang.reflect.Field f = null;545try {546f = readField(field);547if (Modifier.isFinal(f.getModifiers())) return;548f.setAccessible(true);549f.setChar(obj, field.getValue(getObj()));550} catch (Exception ex) {551printFieldSetError(f, ex);552}553}554555public void doBoolean(BooleanField field, boolean isVMField) {556java.lang.reflect.Field f = null;557try {558f = readField(field);559if (Modifier.isFinal(f.getModifiers())) return;560f.setAccessible(true);561f.setBoolean(obj, field.getValue(getObj()));562} catch (Exception ex) {563printFieldSetError(f, ex);564}565}566567public void doShort(ShortField field, boolean isVMField) {568java.lang.reflect.Field f = null;569try {570f = readField(field);571if (Modifier.isFinal(f.getModifiers())) return;572f.setAccessible(true);573f.setShort(obj, field.getValue(getObj()));574} catch (Exception ex) {575printFieldSetError(f, ex);576}577}578579public void doInt(IntField field, boolean isVMField) {580java.lang.reflect.Field f = null;581try {582f = readField(field);583if (Modifier.isFinal(f.getModifiers())) return;584f.setAccessible(true);585f.setInt(obj, field.getValue(getObj()));586} catch (Exception ex) {587printFieldSetError(f, ex);588}589}590591public void doLong(LongField field, boolean isVMField) {592java.lang.reflect.Field f = null;593try {594f = readField(field);595if (Modifier.isFinal(f.getModifiers())) return;596f.setAccessible(true);597f.setLong(obj, field.getValue(getObj()));598} catch (Exception ex) {599printFieldSetError(f, ex);600}601}602603public void doFloat(FloatField field, boolean isVMField) {604java.lang.reflect.Field f = null;605try {606f = readField(field);607if (Modifier.isFinal(f.getModifiers())) return;608f.setAccessible(true);609f.setFloat(obj, field.getValue(getObj()));610} catch (Exception ex) {611printFieldSetError(f, ex);612}613}614615public void doDouble(DoubleField field, boolean isVMField) {616java.lang.reflect.Field f = null;617try {618f = readField(field);619if (Modifier.isFinal(f.getModifiers())) return;620f.setAccessible(true);621f.setDouble(obj, field.getValue(getObj()));622} catch (Exception ex) {623printFieldSetError(f, ex);624}625}626627public void doCInt(CIntField field, boolean isVMField) {628throw new RuntimeException("should not reach here!");629}630}631632public Class readClass(InstanceKlass kls) throws ClassNotFoundException {633Class cls = (Class) getFromObjTable(kls);634if (cls == null) {635cls = Class.forName(kls.getName().asString().replace('/', '.'), true, cl);636putIntoObjTable(kls, cls);637}638return cls;639}640641public Object readMethodOrConstructor(sun.jvm.hotspot.oops.Method m)642throws NoSuchMethodException, ClassNotFoundException {643String name = m.getName().asString();644if (name.equals("<init>")) {645return readConstructor(m);646} else {647return readMethod(m);648}649}650651public java.lang.reflect.Method readMethod(sun.jvm.hotspot.oops.Method m)652throws NoSuchMethodException, ClassNotFoundException {653java.lang.reflect.Method result = (java.lang.reflect.Method) getFromObjTable(m);654if (result == null) {655Class<?> clz = readClass(m.getMethodHolder());656String name = m.getName().asString();657Class[] paramTypes = getParamTypes(m.getSignature());658result = clz.getMethod(name, paramTypes);659putIntoObjTable(m, result);660}661return result;662}663664public java.lang.reflect.Constructor readConstructor(sun.jvm.hotspot.oops.Method m)665throws NoSuchMethodException, ClassNotFoundException {666java.lang.reflect.Constructor result = (java.lang.reflect.Constructor) getFromObjTable(m);667if (result == null) {668Class<?> clz = readClass(m.getMethodHolder());669String name = m.getName().asString();670Class[] paramTypes = getParamTypes(m.getSignature());671result = clz.getDeclaredConstructor(paramTypes);672putIntoObjTable(m, result);673}674return result;675}676677public java.lang.reflect.Field readField(sun.jvm.hotspot.oops.Field f)678throws NoSuchFieldException, ClassNotFoundException {679java.lang.reflect.Field result = (java.lang.reflect.Field) fieldMap.get(f);680if (result == null) {681FieldIdentifier fieldId = f.getID();682Class clz = readClass((InstanceKlass) f.getFieldHolder());683String name = fieldId.getName();684try {685result = clz.getField(name);686} catch (NoSuchFieldException nsfe) {687result = clz.getDeclaredField(name);688}689fieldMap.put(f, result);690}691return result;692}693694protected final ClassLoader cl;695protected Map<Object, Object> oopToObjMap;696protected Map<sun.jvm.hotspot.oops.Field, java.lang.reflect.Field> fieldMap;697698protected void putIntoObjTable(Oop oop, Object obj) {699oopToObjMap.put(oop, obj);700}701702protected Object getFromObjTable(Oop oop) {703return oopToObjMap.get(oop);704}705706protected void putIntoObjTable(Metadata oop, Object obj) {707oopToObjMap.put(oop, obj);708}709710protected Object getFromObjTable(Metadata oop) {711return oopToObjMap.get(oop);712}713714protected class SignatureParser extends SignatureIterator {715protected Vector<Class<?>> tmp = new Vector<>();716717public SignatureParser(Symbol s) {718super(s);719}720721public void doBool () { tmp.add(Boolean.TYPE); }722public void doChar () { tmp.add(Character.TYPE); }723public void doFloat () { tmp.add(Float.TYPE); }724public void doDouble() { tmp.add(Double.TYPE); }725public void doByte () { tmp.add(Byte.TYPE); }726public void doShort () { tmp.add(Short.TYPE); }727public void doInt () { tmp.add(Integer.TYPE); }728public void doLong () { tmp.add(Long.TYPE); }729public void doVoid () {730if(isReturnType()) {731tmp.add(Void.TYPE);732} else {733throw new RuntimeException("should not reach here");734}735}736737public void doObject(int begin, int end) {738tmp.add(getClass(begin, end));739}740741public void doArray (int begin, int end) {742int inner = arrayInnerBegin(begin);743Class elemCls = null;744switch (_signature.getByteAt(inner)) {745case 'B': elemCls = Boolean.TYPE; break;746case 'C': elemCls = Character.TYPE; break;747case 'D': elemCls = Double.TYPE; break;748case 'F': elemCls = Float.TYPE; break;749case 'I': elemCls = Integer.TYPE; break;750case 'J': elemCls = Long.TYPE; break;751case 'S': elemCls = Short.TYPE; break;752case 'Z': elemCls = Boolean.TYPE; break;753case 'L': elemCls = getClass(inner + 1, end); break;754default: break;755}756757int dimension = inner - begin;758// create 0 x 0 ... array and get class from that759int[] dimArray = new int[dimension];760tmp.add(java.lang.reflect.Array.newInstance(elemCls, dimArray).getClass());761}762763protected Class getClass(int begin, int end) {764String className = getClassName(begin, end);765try {766return Class.forName(className, true, cl);767} catch (Exception e) {768if (DEBUG) {769debugPrintln("Can't load class " + className);770}771throw new RuntimeException(e);772}773}774775protected String getClassName(int begin, int end) {776StringBuilder buf = new StringBuilder();777for (int i = begin; i < end; i++) {778char c = (char) (_signature.getByteAt(i) & 0xFF);779if (c == '/') {780buf.append('.');781} else {782buf.append(c);783}784}785return buf.toString();786}787788protected int arrayInnerBegin(int begin) {789while (_signature.getByteAt(begin) == '[') {790++begin;791}792return begin;793}794795public int getNumParams() {796return tmp.size();797}798799public Enumeration getParamTypes() {800return tmp.elements();801}802}803804protected Class[] getParamTypes(Symbol signature) {805SignatureParser sp = new SignatureParser(signature);806sp.iterateParameters();807Class result[] = new Class[sp.getNumParams()];808Enumeration e = sp.getParamTypes();809int i = 0;810while (e.hasMoreElements()) {811result[i] = (Class) e.nextElement();812i++;813}814return result;815}816}817818819