public void sawOpcode(int seen) { try { if ((seen == INVOKEINTERFACE) && (getClassConstantOperand().equals("java/sql/ResultSet"))) { String methodName = getNameConstantOperand(); if ((methodName.startsWith("get") && dbFieldTypesSet.contains(methodName.substring(3))) || (methodName.startsWith("update") && dbFieldTypesSet.contains(methodName.substring(6)))) { String signature = getSigConstantOperand(); Type[] argTypes = Type.getArgumentTypes(signature); int numParms = argTypes.length; if (stack.getStackDepth() >= numParms) { OpcodeStack.Item item = stack.getStackItem(numParms-1); Object cons = item.getConstant(); if ((cons != null) && ("I".equals(item.getSignature())) && (((Integer) cons).intValue() == 0)) { bugReporter.reportBug(new BugInstance(this, "BRSA_BAD_RESULTSET_ACCESS", NORMAL_PRIORITY) .addClassAndMethod(this) .addSourceLine(this)); } } } } } finally { stack.sawOpcode(this, seen); } }
/** * Determines whether a method is compatible with the Method of * this definition. * @param aMethodName the name of the method to check. * @param aArgTypes the method argument types. * @return true if the method is compatible with the Method of * this definition. */ public boolean isCompatible(String aMethodName, Type[] aArgTypes) { // same name? if (!getName().equals(aMethodName)) { return false; } // compatible argument types? final Type[] methodTypes = getArgumentTypes(); if (methodTypes.length != aArgTypes.length) { return false; } for (int i = 0; i < aArgTypes.length; i++) { if (!Utils.isCompatible(aArgTypes[i], methodTypes[i])) { return false; } } return true; }
/** * Finds the narrowest method that is compatible with a method. * An invocation of the given method can be resolved as an invocation * of the narrowest method. * @param aClassName the class for the method. * @param aMethodName the name of the method. * @param aArgTypes the types for the method. * @return the narrowest compatible method. */ public MethodDefinition findNarrowestMethod( String aClassName, String aMethodName, Type[] aArgTypes) { MethodDefinition result = null; final String javaClassName = mJavaClass.getClassName(); if (Repository.instanceOf(aClassName, javaClassName)) { // check all for (int i = 0; i < mMethodDefs.length; i++) { // TODO: check access privileges if (mMethodDefs[i].isCompatible(aMethodName, aArgTypes)) { if (result == null) { result = mMethodDefs[i]; } //else if (mMethodDefs[i].isAsNarrow(result)) { else if (result.isCompatible(mMethodDefs[i])) { result = mMethodDefs[i]; } } } } return result; }
/** * Check the signature of defineClass0 * @param args */ private static void assertSupported(Type[] args) { if (args.length >= 5 && ( args[0].getSignature().equals("Ljava/lang/String;") && args[1].getSignature().equals("[B") && args[2].getSignature().equals("I") && args[3].getSignature().equals("I") && args[4].getSignature().equals("Ljava/security/ProtectionDomain;") )) ; else { StringBuffer sign = new StringBuffer("("); for (int i = 0; i < args.length; i++) { sign.append(args[i].toString()); if (i < args.length - 1) sign.append(", "); } sign.append(")"); throw new Error("non standard JDK, native call not supported " + sign.toString()); } }
private static boolean isIllegalFinalType(Type type, ClassContext classContext) { if (type instanceof ObjectType) { try { String className = ((ObjectType) type).getClassName(); if (className.startsWith("java.")) { // Types in java.lang are final for security reasons. return false; } JavaClass cls = classContext.getAnalysisContext().lookupClass(className); return cls.isFinal() && !cls.isEnum(); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } return false; }
private void generateFields(RootClass k, ConstantPoolGen cp, ClassGen cg) { RootMember[] members = k.getMembers(); for (int i = 0; i < members.length; i++) { if (cg.containsField(members[i].getName()) == null) { Type type = ((BasicMember) members[i]).getJavaType(); if (type != null) { FieldGen fg = new FieldGen(ACC_PRIVATE, type, members[i].getName(), cp); cg.addField(fg.getField()); } } } }
private boolean available_slot(Type[] types, int ind, Type t) { Type tp = types[ind]; if (tp != null) { if (t.equals(tp)) { return true; } return false; } if (t.equals(Type.LONG) || t.equals(Type.DOUBLE)) { if (types[ind + 1] != null) { return false; } types[ind + 1] = Type.VOID; } types[ind] = t; return true; }
static String[] getAllLocalDecls(Method m) { LocalVariable[] lt = getLocalTable(m).getLocalVariableTable(); Vector<String> v = new Vector<String>(); for (int i = 0; i < lt.length; i++) { LocalVariable l = lt[i]; Type tp = Type.getType(l.getSignature()); String e = tp.toString() + " " + generatedLocalName(tp, l.getName()) + ";"; if (!v.contains(e)) { v.addElement(e); } } String[] result = new String[v.size()]; result = v.toArray(result); // for (int i = 0; i < v.size(); i++) { // result[i] = (String) v.elementAt(i); // System.out.println("localdecls for " + m + ": " + result[i]); // } return result; }
InstructionHandle insertDeleteSpawncounter(InstructionList il, InstructionHandle i, int maxLocals) { // In this case, jumps to the return must in fact jump to // the new instruction sequence! So, we change the instruction // at the handle. // First, save the return instruction. Instruction r = i.getInstruction(); i.setInstruction(new ALOAD(maxLocals)); i = il .append(i, ins_f.createInvoke( "ibis.cashmere.impl.spawnSync.SpawnCounter", "deleteSpawnCounter", Type.VOID, new Type[] { spawnCounterType }, Constants.INVOKESTATIC)); i = il.append(i, r); return i; }
InstructionHandle pushParams(InstructionList il, Method m) { Type[] params = mtab.typesOfParams(m); InstructionHandle pos = il.getStart(); for (int i = 0, param = 0; i < params.length; i++, param++) { if (params[i].equals(Type.BOOLEAN) || params[i].equals(Type.BYTE) || params[i].equals(Type.SHORT) || params[i].equals(Type.CHAR) || params[i].equals(Type.INT)) { il.insert(pos, new ILOAD(param)); } else if (params[i].equals(Type.FLOAT)) { il.insert(pos, new FLOAD(param)); } else if (params[i].equals(Type.LONG)) { il.insert(pos, new LLOAD(param)); param++; } else if (params[i].equals(Type.DOUBLE)) { il.insert(pos, new DLOAD(param)); param++; } else { il.insert(pos, new ALOAD(param)); } } return pos; }
InstructionHandle rewriteStore(MethodGen m, InstructionList il, InstructionHandle i, int maxLocals, String localClassName) { LocalVariableInstruction curr = (LocalVariableInstruction) (i .getInstruction()); Type type = mtab.getLocalType(m, curr, i.getPosition()); if (type == null) { return i; } String name = mtab.getLocalName(m, curr, i.getPosition()); String fieldName = MethodTable.generatedLocalName(type, name); i.setInstruction(new ALOAD(maxLocals)); i = i.getNext(); if (type.equals(Type.LONG) || type.equals(Type.DOUBLE)) { il.insert(i, new DUP_X2()); il.insert(i, new POP()); } else { il.insert(i, new SWAP()); } i = il.insert(i, ins_f.createFieldAccess(localClassName, fieldName, type, Constants.PUTFIELD)); return i; }
InstructionHandle rewriteLoad(MethodGen m, InstructionList il, InstructionHandle i, int maxLocals, String localClassName) { LocalVariableInstruction curr = (LocalVariableInstruction) (i .getInstruction()); Type type = mtab.getLocalType(m, curr, i.getPosition()); if (type == null) { return i; } String name = mtab.getLocalName(m, curr, i.getPosition()); String fieldName = MethodTable.generatedLocalName(type, name); i.setInstruction(new ALOAD(maxLocals)); i = i.getNext(); i = il.insert(i, ins_f.createFieldAccess(localClassName, fieldName, type, Constants.GETFIELD)); return i; }
/** Instantiate from an existing method. * * @param method method * @param className class name containing this method * @param constantPoolGen constant pool */ public MethodGen(Method method, String className, ConstantPoolGen constantPoolGen) { super(method, className, constantPoolGen); // Analyze how many stack positions are for parameters. // We won't touch those. parameterPos = isStatic() ? 0 : 1; Type[] parameters = getArgumentTypes(); parameterPos += parameters.length; for (int i = 0; i < parameters.length; i++) { if (parameters[i].equals(Type.LONG) || parameters[i].equals(Type.DOUBLE)) { parameterPos++; } } }
@Override public String getSignature() { StringBuilder sb = new StringBuilder(""); Type[] arguments = method.getArgumentTypes(); boolean first = true; for (Type argument : arguments) { if (first) { first = false; sb.append(argument); } else { sb.append(", ").append(argument); } } return sb.toString(); }
/** * Creates a method class$(String) which is used * during SomeClass.class instruction * * @param generatedClassName the instance class name */ protected void createHelperMethodForDotClassCalls(String generatedClassName) { InstructionList il = new InstructionList(); MethodGen method = new MethodGen(Constants.ACC_STATIC, new ObjectType("java.lang.Class"), new Type[]{Type.STRING}, new String[]{"arg0"}, "class$", generatedClassName, il, constantsPool); InstructionHandle ih0 = il.append(InstructionFactory.createLoad(Type.OBJECT, 0)); il.append(factory.createInvoke("java.lang.Class", "forName", new ObjectType("java.lang.Class"), new Type[]{Type.STRING}, Constants.INVOKESTATIC)); InstructionHandle ih4 = il.append(InstructionFactory.createReturn(Type.OBJECT)); InstructionHandle ih5 = il.append(InstructionFactory.createStore(Type.OBJECT, 1)); il.append(factory.createNew("java.lang.NoClassDefFoundError")); il.append(InstructionConstants.DUP); il.append(InstructionFactory.createLoad(Type.OBJECT, 1)); il.append(factory.createInvoke("java.lang.Throwable", "getMessage", Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); il.append(factory.createInvoke("java.lang.NoClassDefFoundError", "<init>", Type.VOID, new Type[]{Type.STRING}, Constants.INVOKESPECIAL)); il.append(InstructionConstants.ATHROW); method.addExceptionHandler(ih0, ih4, ih5, new ObjectType("java.lang.ClassNotFoundException")); method.setMaxStack(); method.setMaxLocals(); classGen.addMethod(method.getMethod()); il.dispose(); }
private void generateEqualsMethod(String generatedClassName) { /* public boolean equals(Object o) { * return stubHelper.isEquals(this,o); * } */ InstructionList il = new InstructionList(); MethodGen method = new MethodGen(Constants.ACC_PUBLIC, Type.BOOLEAN, new Type[]{Type.OBJECT}, new String[]{"arg0"}, "equals", generatedClassName, il, constantsPool); il.append(InstructionFactory.createLoad(Type.OBJECT, 0)); il.append(factory.createFieldAccess(generatedClassName, "stubHelper", new ObjectType("org.codehaus.jremoting.client.StubHelper"), Constants.GETFIELD)); il.append(InstructionFactory.createLoad(Type.OBJECT, 0)); il.append(InstructionFactory.createLoad(Type.OBJECT, 1)); il.append(factory.createInvoke("org.codehaus.jremoting.client.StubHelper", "isEquals", Type.BOOLEAN, new Type[]{Type.OBJECT, Type.OBJECT}, Constants.INVOKEINTERFACE)); il.append(InstructionFactory.createReturn(Type.INT)); method.setMaxStack(); method.setMaxLocals(); classGen.addMethod(method.getMethod()); il.dispose(); }
/** * Method getBCELType. * Maps the java datatype and the BCEL datatype * * @param clazz the class * @return Type the type */ protected Type getBCELType(Class clazz) { if (clazz.isPrimitive()) { return getBCELPrimitiveType(clazz.getName()); } else if (!clazz.isArray()) { return new ObjectType(clazz.getName()); } else { String className = clazz.getName(); int index = className.lastIndexOf('['); int arrayDepth = className.indexOf('[') - className.lastIndexOf('[') + 1; if (className.charAt(index + 1) == 'L') { return new ArrayType(new ObjectType(clazz.getComponentType().getName()), arrayDepth); } return new ArrayType(getBCELPrimitiveType(className.substring(arrayDepth)), arrayDepth); } }
/** * Returns a string representation of a given object native value. * * @param type - a Class object that wraps a data type. * @param value - an object that wraps a value of a primitive data type. * @return a string that represents a native data type. */ public static String getNativeValue(Type type, ConstantValue value) { StringBuffer result = new StringBuffer(); if (type == Type.INT) { result.append(value.toString()).append('L'); } else if (type == Type.BYTE) { result.append(value.toString()).append('L'); } else if (type == Type.LONG) { result.append(value.toString()).append("LL"); } else if (type == Type.FLOAT) { result.append(value.toString()).append('f'); } else if (type == Type.DOUBLE) { result.append(value.toString()); } else if (type == Type.SHORT) { result.append(value.toString()).append('L'); } else if (type == Type.CHAR) { result.append(value.toString()).append('L'); } else if (type == Type.BOOLEAN) { result.append(value.toString()).append('L'); } return result.toString(); }
private QMethodAndArgs make(String fullSignatureWithArgs) { int firstSplitIndex = fullSignatureWithArgs.indexOf('.'); int secondSplitIndex = fullSignatureWithArgs.indexOf('('); String qualifiedTypeWithSlashes = fullSignatureWithArgs.substring(0, firstSplitIndex); String qtype = qualifiedTypeWithSlashes.replace('/', '.'); String method = fullSignatureWithArgs.substring(firstSplitIndex + 1, secondSplitIndex); List<String> argumentTypes = new ArrayList<>(); Type[] bcelTypes = Type.getArgumentTypes(fullSignatureWithArgs.substring(secondSplitIndex)); for (Type t : bcelTypes) { argumentTypes.add(t.toString()); // toString returns them in human-readable dot notation } return new QMethodAndArgs(qtype, method, argumentTypes); }
@Override protected ReferenceType mergeReferenceTypes(ReferenceType aRef, ReferenceType bRef) throws DataflowAnalysisException { byte aType = aRef.getType(); byte bType = bRef.getType(); if (isExtendedStringType(aType) || isExtendedStringType(bType)) { // If both types are the same extended String type, // then the same type is returned. Otherwise, extended // types are downgraded to plain java.lang.String, // and a standard merge is applied. if (aType == bType) { return aRef; } if (isExtendedStringType(aType)) { aRef = Type.STRING; } if (isExtendedStringType(bType)) { bRef = Type.STRING; } } return super.mergeReferenceTypes(aRef, bRef); }
private void pushByInvoke(DismantleBytecode dbc, boolean popThis) { String signature = dbc.getSigConstantOperand(); if (dbc.getNameConstantOperand().equals("<init>") && signature.endsWith(")V") && popThis) { pop(PreorderVisitor.getNumberArguments(signature)); Item constructed = pop(); if (getStackDepth() > 0) { Item next = getStackItem(0); if (constructed.equals(next)) { next = new Item(next); next.source = XFactory.createReferencedXMethod(dbc); next.pc = dbc.getPC(); replace(0, next); } } return; } pop(PreorderVisitor.getNumberArguments(signature) + (popThis ? 1 : 0)); pushBySignature(Type.getReturnType(signature).getSignature(), dbc); }
/** * Get array of Obligation types corresponding to the parameters of the * given method. * * @param xmethod * a method * @return array of Obligation types for each of the method's parameters; a * null element means the corresponding parameter is not an * Obligation type */ public Obligation[] getParameterObligationTypes(XMethod xmethod) { Type[] paramTypes = Type.getArgumentTypes(xmethod.getSignature()); Obligation[] result = new Obligation[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { if (!(paramTypes[i] instanceof ObjectType)) { continue; } try { result[i] = getObligationByType((ObjectType) paramTypes[i]); } catch (ClassNotFoundException e) { Global.getAnalysisCache().getErrorLogger().reportMissingClass(e); } } return result; }
public static CodeExceptionGen merge(@CheckForNull TypeMerger m, CodeExceptionGen e1, CodeExceptionGen e2) { if (e1 == null) return e2; if (e2 == null) return e1; if (m == null) return e1; if ( ! e1.getHandlerPC().equals( e2.getHandlerPC() ) ){ // log error return e1; } try { Type t = m.mergeTypes(e1.getCatchType(), e2.getCatchType()); return new CodeExceptionGen(e1.getStartPC(), e1.getEndPC(), e1.getHandlerPC(), (ObjectType) t); } catch (DataflowAnalysisException e) { // TODO Auto-generated catch block e.printStackTrace(); return e1; } }
protected void addTransactionMethod(ParsedMethod pm) { String et = EntityTransaction.class.getCanonicalName(); GeneratedMethod gm = new GeneratedMethod(pm); InstructionList il = gm.start(); writeMethodPreamble(gm, il); il.append(_factory.createInvoke(EM_TYPE, "getTransaction", new ObjectType(et), Type.NO_ARGS, Constants.INVOKEINTERFACE)); il.append(_factory.createInvoke(et, pm.getMethod().getName(), Type.VOID, Type.NO_ARGS, Constants.INVOKEINTERFACE)); il.append(InstructionFactory.createReturn(Type.VOID)); gm.done(); }
public Type mergeTypes(Type a, Type b) throws DataflowAnalysisException { byte aType = a.getType(), bType = b.getType(); if (aType == T_TOP) // Top is the identity element return b; else if (bType == T_TOP) // Top is the identity element return a; else if (aType == T_BOTTOM || bType == T_BOTTOM) // Bottom meet anything is bottom return BottomType.instance(); else if (isReferenceType(aType) && isReferenceType(bType)) { // Two object types! // Handle the Null type, which serves as a special "top" // value for reference types. if (aType == T_NULL) return b; else if (bType == T_NULL) return a; ReferenceType aRef = (ReferenceType) a; ReferenceType bRef = (ReferenceType) b; return mergeReferenceTypes(aRef, bRef); } else if (isReferenceType(aType) || isReferenceType(bType)) // Object meet non-object is bottom return BottomType.instance(); else if (aType == bType) // Same non-object type? return a; else if (isIntegerType(aType) && isIntegerType(bType)) // Two different integer types - use T_INT return Type.INT; else // Default - types are incompatible return BottomType.instance(); }
/** * Default implementation of merging reference types. * This just returns the first common superclass, which is compliant * with the JVM Spec. Subclasses may override this method * in order to implement extended type rules. * * @param aRef a ReferenceType * @param bRef a ReferenceType * @return the merged Type */ protected Type mergeReferenceTypes(ReferenceType aRef, ReferenceType bRef) throws DataflowAnalysisException { // Two concrete object types. // According to the JVM spec, 2nd edition, 4.9.2, // the result of merging types is the "first common superclass". // Interfaces are NOT considered! // This will use the Repository to look up classes. try { // Special case: ExceptionObjectTypes. // We want to preserve the ExceptionSets associated, // in order to track the exact set of exceptions if (isObjectType(aRef.getType()) && isObjectType(bRef.getType()) && (aRef.getType() == T_EXCEPTION || bRef.getType() == T_EXCEPTION)) { ExceptionSet union = exceptionSetFactory.createExceptionSet(); updateExceptionSet(union, (ObjectType) aRef); updateExceptionSet(union, (ObjectType) bRef); return ExceptionObjectType.fromExceptionSet(union); } return aRef.getFirstCommonSuperclass(bRef); } catch (ClassNotFoundException e) { lookupFailureCallback.reportMissingClass(e); throw new DataflowAnalysisException("Repository lookup failure: " + e.toString(), e); } }
/** * Initialize object from an exception set. * * @param exceptionSet the exception set * @return a Type that is a supertype of all of the exceptions in * the exception set */ public static Type fromExceptionSet(ExceptionSet exceptionSet) throws ClassNotFoundException { Type commonSupertype = exceptionSet.getCommonSupertype(); if (commonSupertype.getType() != T_OBJECT) return commonSupertype; ObjectType exceptionSupertype = (ObjectType) commonSupertype; return new ExceptionObjectType(exceptionSupertype.getClassName(), exceptionSet); }
/** * Get the least (lowest in the lattice) common supertype * of the exceptions in the set. Returns the special TOP * type if the set is empty. */ public Type getCommonSupertype() throws ClassNotFoundException { if (commonSupertype != null) return commonSupertype; if (isEmpty()) { // This probably means that we're looking at an // infeasible exception path. return TypeFrame.getTopType(); } // Compute first common superclass ThrownExceptionIterator i = iterator(); ReferenceType result = i.next(); while (i.hasNext()) { result = result.getFirstCommonSuperclass(i.next()); if (result == null) { // This should only happen if the class hierarchy // is incomplete. We'll just be conservative. result = Type.THROWABLE; break; } } // Cache and return the result commonSupertype = result; return result; }
/** * Adds a reference for an invocation in the invoked method definition. * The invocation is of the form class.method(args). * @param aInvokeRef the invocation reference. */ public void addInvokeReference(InvokeReference aInvokeRef) { // find the class for the instruction final String className = aInvokeRef.getClassName(); JavaClass javaClass = Repository.lookupClass(className); final String methodName = aInvokeRef.getName(); final Type[] argTypes = aInvokeRef.getArgTypes(); // search up the class hierarchy for the class containing the // method definition. MethodDefinition narrowest = null; while ((javaClass != null) && (narrowest == null)) { final JavaClassDefinition javaClassDef = (JavaClassDefinition) mJavaClasses.get(javaClass); if (javaClassDef != null) { // find narrowest compatible in the current class narrowest = javaClassDef.findNarrowestMethod( className, methodName, argTypes); if (narrowest != null) { narrowest.addReference(aInvokeRef); } } // search the parent javaClass = javaClass.getSuperClass(); } }
/** * Determines whether there is reference to a given Method in this JavaClass * definition or a definition in a superclass. * @param aMethodDef the Method to check. * @param aReferenceDAO reference DAO. * @return true if there is a reference to the method of aMethodDef in * this JavaClass or a superclass. */ public boolean hasReference( MethodDefinition aMethodDef, ReferenceDAO aReferenceDAO) { final String methodName = aMethodDef.getName(); final Type[] argTypes = aMethodDef.getArgumentTypes(); // search the inheritance hierarchy JavaClass currentJavaClass = getJavaClass(); while (currentJavaClass != null) { final JavaClassDefinition javaClassDef = aReferenceDAO.findJavaClassDef(currentJavaClass); if (javaClassDef != null) { final MethodDefinition methodDef = javaClassDef.findNarrowestMethod( getJavaClass().getClassName(), methodName, argTypes); if ((methodDef != null) && (methodDef.hasReference(getJavaClass()))) { return true; } } currentJavaClass = currentJavaClass.getSuperClass(); } return false; }
/** * @return A org.apache.bcel.classfile.Method corresponding to * java.lang.reflect.Method if any */ public Method getMethod(java.lang.reflect.Method m) { for(int i = 0; i < methods.length; i++) { Method method = methods[i]; if(m.getName().equals(method.getName()) && (m.getModifiers() == method.getModifiers()) && Type.getSignature(m).equals(method.getSignature())) { return method; } } return null; }
/** * Adds information about the local variable in slot 'slot'. Automatically * adds information for slot+1 if 't' is Type.LONG or Type.DOUBLE. * @throws LocalVariableInfoInconsistentException if the new information conflicts * with already gathered information. */ public void add(int slot, String name, int startpc, int length, Type t) throws LocalVariableInfoInconsistentException{ // The add operation on LocalVariableInfo may throw the '...Inconsistent...' exception, we don't throw it explicitely here. if (slot < 0 || slot >= localVariableInfos.length){ throw new AssertionViolatedException("Slot number for local variable information out of range."); } localVariableInfos[slot].add(name, startpc, length, t); if (t == Type.LONG) localVariableInfos[slot+1].add(name, startpc, length, LONG_Upper.theInstance()); if (t == Type.DOUBLE) localVariableInfos[slot+1].add(name, startpc, length, DOUBLE_Upper.theInstance()); }
/** * Adds information about name and type for a given offset. * @throws LocalVariableInfoInconsistentException if the new information conflicts * with already gathered information. */ private void add(int offset, String name, Type t) throws LocalVariableInfoInconsistentException{ if (getName(offset) != null){ if (! getName(offset).equals(name)){ throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+"' a local variable has two different names: '"+getName(offset)+"' and '"+name+"'."); } } if (getType(offset) != null){ if (! getType(offset).equals(t)){ throw new LocalVariableInfoInconsistentException("At bytecode offset '"+offset+"' a local variable has two different types: '"+getType(offset)+"' and '"+t+"'."); } } setName(offset, name); setType(offset, t); }
/** * Creates a new LocalVariables object. */ public LocalVariables(int maxLocals){ locals = new Type[maxLocals]; for (int i=0; i<maxLocals; i++){ locals[i] = Type.UNKNOWN; } }
/** * Sets a new Type for the given local variable slot. */ public void set(int i, Type type){ if (type == Type.BYTE || type == Type.SHORT || type == Type.BOOLEAN || type == Type.CHAR){ throw new AssertionViolatedException("LocalVariables do not know about '"+type+"'. Use Type.INT instead."); } locals[i] = type; }