001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018package org.apache.bcel.generic; 019 020import java.util.StringTokenizer; 021 022import org.apache.bcel.Const; 023import org.apache.bcel.classfile.Constant; 024import org.apache.bcel.classfile.ConstantCP; 025import org.apache.bcel.classfile.ConstantPool; 026 027/** 028 * Super class for the INVOKExxx family of instructions. 029 * 030 * @version $Id: InvokeInstruction.java 1752106 2016-07-10 20:02:39Z britter $ 031 */ 032public abstract class InvokeInstruction extends FieldOrMethod implements ExceptionThrower, 033 StackConsumer, StackProducer { 034 035 /** 036 * Empty constructor needed for the Class.newInstance() statement in 037 * Instruction.readInstruction(). Not to be used otherwise. 038 */ 039 InvokeInstruction() { 040 } 041 042 043 /** 044 * @param index to constant pool 045 */ 046 protected InvokeInstruction(final short opcode, final int index) { 047 super(opcode, index); 048 } 049 050 051 /** 052 * @return mnemonic for instruction with symbolic references resolved 053 */ 054 @Override 055 public String toString( final ConstantPool cp ) { 056 final Constant c = cp.getConstant(super.getIndex()); 057 final StringTokenizer tok = new StringTokenizer(cp.constantToString(c)); 058 return Const.getOpcodeName(super.getOpcode()) + " " + tok.nextToken().replace('.', '/') 059 + tok.nextToken(); 060 } 061 062 063 /** 064 * Also works for instructions whose stack effect depends on the 065 * constant pool entry they reference. 066 * @return Number of words consumed from stack by this instruction 067 */ 068 @Override 069 public int consumeStack( final ConstantPoolGen cpg ) { 070 int sum; 071 if ((super.getOpcode() == Const.INVOKESTATIC) || (super.getOpcode() == Const.INVOKEDYNAMIC)) { 072 sum = 0; 073 } else { 074 sum = 1; // this reference 075 } 076 077 final String signature = getSignature(cpg); 078 sum += Type.getArgumentTypesSize(signature); 079 return sum; 080 } 081 082 083 /** 084 * Also works for instructions whose stack effect depends on the 085 * constant pool entry they reference. 086 * @return Number of words produced onto stack by this instruction 087 */ 088 @Override 089 public int produceStack( final ConstantPoolGen cpg ) { 090 final String signature = getSignature(cpg); 091 return Type.getReturnTypeSize(signature); 092 } 093 094 /** 095 * This overrides the deprecated version as we know here that the referenced class 096 * may legally be an array. 097 * 098 * @return name of the referenced class/interface 099 * @throws IllegalArgumentException if the referenced class is an array (this should not happen) 100 */ 101 @Override 102 public String getClassName( final ConstantPoolGen cpg ) { 103 final ConstantPool cp = cpg.getConstantPool(); 104 final ConstantCP cmr = (ConstantCP) cp.getConstant(super.getIndex()); 105 final String className = cp.getConstantString(cmr.getClassIndex(), Const.CONSTANT_Class); 106 return className.replace('/', '.'); 107 } 108 109 /** @return return type of referenced method. 110 */ 111 @Override 112 public Type getType( final ConstantPoolGen cpg ) { 113 return getReturnType(cpg); 114 } 115 116 117 /** @return name of referenced method. 118 */ 119 public String getMethodName( final ConstantPoolGen cpg ) { 120 return getName(cpg); 121 } 122 123 124 /** @return return type of referenced method. 125 */ 126 public Type getReturnType( final ConstantPoolGen cpg ) { 127 return Type.getReturnType(getSignature(cpg)); 128 } 129 130 131 /** @return argument types of referenced method. 132 */ 133 public Type[] getArgumentTypes( final ConstantPoolGen cpg ) { 134 return Type.getArgumentTypes(getSignature(cpg)); 135 } 136 137}