📄 methodinfo.java
字号:
case opc_agetstatic_checkinit_quick: case opc_aputstatic_checkinit_quick: case opc_getstatic2_quick: case opc_putstatic2_quick: case opc_getstatic2_checkinit_quick: case opc_putstatic2_checkinit_quick: case opc_invokestatic_quick: case opc_invokenonvirtual_quick: case opc_invokesuper_quick: case opc_new_quick: case opc_new_checkinit_quick: case opc_anewarray_quick: case opc_multianewarray_quick: case opc_checkcast_quick: case opc_instanceof_quick: case opc_invokevirtual_quick_w: case opc_getfield_quick_w: case opc_putfield_quick_w: wide[nwide++] = i; i += opcLengths[opcode]; break; default: i += opcLengths[opcode]; break; } } // not knowing any better, we allocated excess capacity. // allocate and fill appropriately-sized arrays. ldcInstructions = new int[ nldc ]; System.arraycopy( ldc, 0, ldcInstructions, 0, nldc ); ldc = null; wideConstantRefInstructions = new int[ nwide ]; System.arraycopy( wide, 0, wideConstantRefInstructions, 0, nwide ); wide = null; } public int opcodeLength (int pc) { int old_pc; int opcode = (int)code[pc]&0xff; switch (opcode) { case opc_tableswitch: old_pc = pc; pc = (pc + 4) & ~3; int low = getInt(pc + 4); int high = getInt(pc + 8); pc += (high - low + 1) * 4 + 12; return pc - old_pc; case opc_lookupswitch: old_pc = pc; pc = (pc + 4) & ~3; int pairs = getInt(pc + 4); pc += pairs * 8 + 8; return pc - old_pc; case opc_wide: if (((int)code[pc + 1]&0xff) == opc_iinc) return 6; return 4; default: return opcLengths[opcode]; } } public void countConstantReferences(ConstantPool cp, boolean isRelocatable) { ConstantObject table[] = cp.getConstants(); super.countConstantReferences(isRelocatable); Attribute.countConstantReferences(methodAttributes, isRelocatable); Attribute.countConstantReferences(codeAttributes, isRelocatable); if (code == null) return; // no code, no relocation if (ldcInstructions == null) { findConstantReferences(); } { int list[] = ldcInstructions; int n = list.length; for (int i = 0; i < n; i++){ int loc = list[i]; if ( loc==-1 ) continue; table[ (int)code[loc+1]&0xff ].incReference(); } } { int list[] = wideConstantRefInstructions; int n = list.length; for (int i = 0; i < n; i++){ int loc = list[i]; if ( loc==-1 ) continue; table[ getUnsignedShort(loc+1) ].incReference(); } } } /* * Call just before writing output. * Ensure sanity among attributes and constants. * Some tables we do here because they need to know code length. * Others we just deligate. */ public void validate(ConstantObject constantPool[]){ int codeLength = (code == null ) ? 0 : code.length; super.validate(); if (methodAttributes != null){ for (int i=0; i<methodAttributes.length; i++){ // this covers the exceptionsThrown and the localVariableTable methodAttributes[i].validate(); } } if (codeAttributes != null){ for (int i=0; i<codeAttributes.length; i++){ codeAttributes[i].validate(); } } if (exceptionTable != null){ validateExceptionTable(); } if (lineNumberTable != null){ for (int i=0; i<lineNumberTable.length; i++){ int startPC = lineNumberTable[i].startPC; if (startPC<0 || startPC >= codeLength){ throw new ValidationException( "Line number table entry startPC out of range in", this); } } } /* * The big job is sweeping the code for constant pool references * and making sure we like what we see. */ if (codeLength != 0){ validateCode(constantPool); } } /* * Helper for validate. * Make sure pc range is in range * Make sure that if there is a catch type, that we like it: * it validates itself, and should be Throwable. */ private void validateExceptionTable(){ int codeLength = (code == null ) ? 0 : code.length; for (int i=0; i<exceptionTable.length; i++){ int startPC = exceptionTable[i].startPC; int endPC = exceptionTable[i].endPC; if (startPC<0 || startPC >= codeLength){ throw new ValidationException( "ExceptionTable entry startPC out of range in", this); } if (endPC<0 || endPC >= codeLength){ throw new ValidationException( "ExceptionTable entry endPC out of range in", this); } if (exceptionTable[i].catchType != null){ exceptionTable[i].catchType.validate(); // make sure that what we're catching is throwable! ClassInfo throwClassInfo = exceptionTable[i].catchType.find(); ClassInfo thisClassInfo = throwClassInfo; while (thisClassInfo != null){ if (thisClassInfo.className.equals("java/lang/Throwable")){ break; // success, we're happy } if (thisClassInfo.className.equals("java/lang/Object")){ // reached top of hierarchy without finding Throwable. BAD throw new ValidationException( "ExceptionTable entry catches non-throwable "+ throwClassInfo.className, this); } thisClassInfo = thisClassInfo.superClassInfo; } // either did break or ventured into unknown superclassdom. // either way we stop here. } } } /* * Helper for validateCode */ /* * These are used to encode the constantType as follows: * The base types (first 4) are never combined with each other. * CP_FIELD can be combined using | with one of * CP_DOUBLE, CP_SINGLE, CP_REF, as well as CP_STATIC. * CP_METHOD can be combined with CP_STATIC. * CP_DOUBLE or CP_SINGLE can also stand alone to represent * references to constants in the pool. * CP_LOADABLE cannot be combined with anything and represents * any literal constant pool entry than can be the target of an ldc * or ldc variant: a String literal, a single-numeric literal or a long-numeric * literal. */ static final int CP_LOADABLE = 0; // any type that can be loaded directly. static final int CP_CLASS = 1; // Class reference static final int CP_STRING = 2; // String reference static final int CP_METHOD = 4; // method reference static final int CP_FIELD = 8; // field reference static final int CP_BASE = 0xf; // all of the above. static final int CP_DOUBLE = 0x10; // double when applied to a field numeric. // or 64-bit const pool entry static final int CP_REF = 0x20; // reference type when applied to a field . static final int CP_STATIC = 0x40; // static method or field static final int CP_SINGLE = 0x80; // non-reference field. // or 32-bit const pool entry private void validateLoadable(ConstantObject constantPool[], int index, int constantType){ if (index <= 0 || index >= constantPool.length){ throw new ValidationException( "Instruction constant pool index out of range in", this); } ConstantObject c = constantPool[index]; if (c == null){ throw new ValidationException( "Instruction constant pool index to illegal entry in", this); } String expected; foundBad: switch(constantType){ case CP_LOADABLE: if (c instanceof StringConstant) return; if (c instanceof SingleValueConstant) return; if (c instanceof DoubleValueConstant) return; if (c instanceof ClassConstant) return; expected = "Directly loadable constant"; break foundBad; case CP_STRING: if (c instanceof StringConstant) return; expected = "String constant"; break foundBad; case CP_SINGLE: // a one-word constant. see use of CP_SINGLE as modifier below. if (c instanceof SingleValueConstant) return; expected = "One-word constant"; break foundBad; case CP_DOUBLE: // a two-word constant. see use of CP_DOUBLE as modifier below. if (c instanceof DoubleValueConstant) return; expected = "Two-word constant"; break foundBad; case CP_CLASS: if (c instanceof ClassConstant) return; expected = "Class reference"; break foundBad; default: // some combination of FIELD or METHOD with modifiers. ClassMemberInfo cm; FMIrefConstant fmiRef; String memberType; fieldOrMethod: switch (constantType & CP_BASE){ case CP_FIELD: if (! (c instanceof FieldConstant)){ expected = "Field reference"; break foundBad; } fmiRef = (FMIrefConstant)c; cm = ((FieldConstant)c).find(); break fieldOrMethod; case CP_METHOD: if (!(c instanceof MethodConstant)){ expected = "Method reference"; break foundBad; } fmiRef = (FMIrefConstant)c; cm = ((MethodConstant)c).find(); break fieldOrMethod; default: expected = "verifyLoadable confusion"; break foundBad; } memberType = fmiRef.sig.type.string; if ((constantType & (CP_DOUBLE|CP_SINGLE)) != 0){ if (memberType.length() != 1){ expected = "Simple type class member"; break foundBad; } switch(memberType.charAt(0)){ case 'B': case 'C': case 'F': case 'I': case 'S': case 'Z': if ((constantType& CP_SINGLE) == 0){ expected = "Long/Double type class member"; break foundBad; } break; case 'D': case 'J': if ((constantType& CP_DOUBLE) == 0){ expected = "Single word scalar type class member"; break foundBad; } break; default: expected = "Simple type class member"; break foundBad; } }else if ((constantType & CP_REF) != 0){ if (memberType.length() <= 1){ expected = "Reference type class member"; break foundBad; } switch(memberType.charAt(0)){ case 'L': case '[': break; default: expected = "Reference type class member"; break foundBad; } } if (cm != null){ // can't look at missing class! if ((constantType & CP_STATIC) != 0){ if (!cm.isStaticMember()){ expected = "Static class member"; break foundBad; } } else { if (cm.isStaticMember()){ expected = "Non-static class member"; break foundBad; } } } // got this far looking at a field/method access. // must be successful. return; } // we got here by doing a break foundBad. // expected is set to something. // c is set to something. // throw something throw new ValidationException(expected+" in "+this, c); } /* * If we were more trusting, we'd use the info already computed * on the location of constant references, such as ldcInstructions. * It may be out of date because of code rewriting due to constant * pool sharing or other transformations. */ void validateCode(ConstantObject constantPool[]) throws DataFormatException { if ( code == null ) return; // no code, no references. int ncode = code.length; byte codeBytes[] = code; int opcode; int index; int constType; for( int i = 0; i < ncode; /*nothing*/){ computedLength:{ noCPAccess:{ 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 computedLength; case opc_lookupswitch: i = (i + 4) & ~3; int pairs = getInt(i+4); i += pairs * 8 + 8; break computedLength; 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 computedLength; case opc_iinc: i += 6; break computedLength; default: throw new DataFormatException( parent.className + "." + name.string + ": unknown wide " + "instruction: " + code[i+1] ); } case opc_ldc: // undifferentiated loadable type. constType = CP_LOADABLE; index = at(codeBytes, i+1); break; case opc_ldc_quick: // single cell, not a string constType = CP_SINGLE; index = at(codeBytes, i+1); break; case opc_aldc_quick: case opc_aldc_ind_quick: // string constType = CP_STRING; index = at(codeBytes, i+1); break; case opc_ldc_w: // undifferentiated loadable type. constType = CP_LOADABLE; index = shortAt(codeBytes, i+1); break; case opc_ldc2_w: case opc_ldc2_w_quick: // double cell constType = CP_DOUBLE; index = shortAt(codeBytes, i+1); break; case opc_aldc_w_quick: case opc_aldc_ind_w_quick: // string constType = CP_STRING; index = shortAt(codeBytes, i+1); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -