Path: blob/master/src/jdk.jdi/share/classes/com/sun/tools/jdi/MethodImpl.java
41161 views
/*1* Copyright (c) 1998, 2017, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.jdi;2627import java.util.ArrayList;28import java.util.List;2930import com.sun.jdi.AbsentInformationException;31import com.sun.jdi.ArrayReference;32import com.sun.jdi.ArrayType;33import com.sun.jdi.ClassNotLoadedException;34import com.sun.jdi.InterfaceType;35import com.sun.jdi.InvalidTypeException;36import com.sun.jdi.Location;37import com.sun.jdi.Method;38import com.sun.jdi.Type;39import com.sun.jdi.Value;40import com.sun.jdi.VirtualMachine;4142public abstract class MethodImpl extends TypeComponentImpl43implements Method44{45private JNITypeParser signatureParser;4647abstract int argSlotCount() throws AbsentInformationException;4849abstract List<Location> allLineLocations(SDE.Stratum stratum,50String sourceName)51throws AbsentInformationException;5253abstract List<Location> locationsOfLine(SDE.Stratum stratum,54String sourceName,55int lineNumber)56throws AbsentInformationException;5758MethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,59long ref, String name, String signature,60String genericSignature, int modifiers) {61super(vm, declaringType, ref, name, signature,62genericSignature, modifiers);63signatureParser = new JNITypeParser(signature);64}6566static MethodImpl createMethodImpl(VirtualMachine vm,67ReferenceTypeImpl declaringType,68long ref,69String name,70String signature,71String genericSignature,72int modifiers) {73if ((modifiers & (VMModifiers.NATIVE | VMModifiers.ABSTRACT)) != 0) {74return new NonConcreteMethodImpl(vm, declaringType, ref,75name, signature,76genericSignature,77modifiers);78} else {79return new ConcreteMethodImpl(vm, declaringType, ref,80name, signature,81genericSignature,82modifiers);83}84}8586public boolean equals(Object obj) {87if ((obj != null) && (obj instanceof MethodImpl)) {88MethodImpl other = (MethodImpl)obj;89return (declaringType().equals(other.declaringType())) &&90(ref() == other.ref()) &&91super.equals(obj);92} else {93return false;94}95}9697public int hashCode() {98return (int)ref();99}100101public final List<Location> allLineLocations()102throws AbsentInformationException {103return allLineLocations(vm.getDefaultStratum(), null);104}105106public List<Location> allLineLocations(String stratumID,107String sourceName)108throws AbsentInformationException {109return allLineLocations(declaringType.stratum(stratumID), sourceName);110}111112public final List<Location> locationsOfLine(int lineNumber)113throws AbsentInformationException {114return locationsOfLine(vm.getDefaultStratum(),115null, lineNumber);116}117118public List<Location> locationsOfLine(String stratumID,119String sourceName,120int lineNumber)121throws AbsentInformationException {122return locationsOfLine(declaringType.stratum(stratumID),123sourceName, lineNumber);124}125126LineInfo codeIndexToLineInfo(SDE.Stratum stratum,127long codeIndex) {128if (stratum.isJava()) {129return new BaseLineInfo(-1, declaringType);130} else {131return new StratumLineInfo(stratum.id(), -1, null, null);132}133}134135/**136* @return a text representation of the declared return type137* of this method.138*/139public String returnTypeName() {140return signatureParser.typeName();141}142143private String returnSignature() {144return signatureParser.signature();145}146147public Type returnType() throws ClassNotLoadedException {148return findType(returnSignature());149}150151public Type findType(String signature) throws ClassNotLoadedException {152ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();153return enclosing.findType(signature);154}155156public List<String> argumentTypeNames() {157return signatureParser.argumentTypeNames();158}159160public List<String> argumentSignatures() {161return signatureParser.argumentSignatures();162}163164Type argumentType(int index) throws ClassNotLoadedException {165ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();166String signature = argumentSignatures().get(index);167return enclosing.findType(signature);168}169170public List<Type> argumentTypes() throws ClassNotLoadedException {171int size = argumentSignatures().size();172List<Type> types = new ArrayList<>(size);173for (int i = 0; i < size; i++) {174Type type = argumentType(i);175types.add(type);176}177178return types;179}180181public int compareTo(Method method) {182ReferenceTypeImpl declaringType = (ReferenceTypeImpl)declaringType();183int rc = declaringType.compareTo(method.declaringType());184if (rc == 0) {185rc = declaringType.indexOf(this) - declaringType.indexOf(method);186}187return rc;188}189190public boolean isAbstract() {191return isModifierSet(VMModifiers.ABSTRACT);192}193194public boolean isDefault() {195return !isModifierSet(VMModifiers.ABSTRACT) &&196!isModifierSet(VMModifiers.STATIC) &&197!isModifierSet(VMModifiers.PRIVATE) &&198declaringType() instanceof InterfaceType;199}200201public boolean isSynchronized() {202return isModifierSet(VMModifiers.SYNCHRONIZED);203}204205public boolean isNative() {206return isModifierSet(VMModifiers.NATIVE);207}208209public boolean isVarArgs() {210return isModifierSet(VMModifiers.VARARGS);211}212213public boolean isBridge() {214return isModifierSet(VMModifiers.BRIDGE);215}216217public boolean isConstructor() {218return name().equals("<init>");219}220221public boolean isStaticInitializer() {222return name().equals("<clinit>");223}224225public boolean isObsolete() {226try {227return JDWP.Method.IsObsolete.process(vm,228declaringType, ref).isObsolete;229} catch (JDWPException exc) {230throw exc.toJDIException();231}232}233234/*235* A container class for the return value to allow236* proper type-checking.237*/238class ReturnContainer implements ValueContainer {239ReturnContainer() {240}241public Type type() throws ClassNotLoadedException {242return returnType();243}244public String typeName(){245return returnTypeName();246}247public String signature() {248return returnSignature(); //type().signature();249}250public Type findType(String signature) throws ClassNotLoadedException {251return MethodImpl.this.findType(signature);252}253}254ReturnContainer retValContainer = null;255ReturnContainer getReturnValueContainer() {256if (retValContainer == null) {257retValContainer = new ReturnContainer();258}259return retValContainer;260}261262/*263* A container class for the argument to allow264* proper type-checking.265*/266class ArgumentContainer implements ValueContainer {267int index;268269ArgumentContainer(int index) {270this.index = index;271}272public Type type() throws ClassNotLoadedException {273return argumentType(index);274}275public String typeName(){276return argumentTypeNames().get(index);277}278public String signature() {279return argumentSignatures().get(index);280}281public Type findType(String signature) throws ClassNotLoadedException {282return MethodImpl.this.findType(signature);283}284}285286/*287* This is a var args method. Thus, its last param is an288* array. If the method has n params, then:289* 1. If there are n args and the last is the same type as the type of290* the last param, do nothing. IE, a String[]291* can be passed to a String...292* 2. If there are >= n arguments and for each arg whose number is >= n,293* the arg type is 'compatible' with the component type of294* the last param, then do295* - create an array of the type of the last param296* - put the n, ... args into this array.297* We might have to do conversions here.298* - put this array into arguments(n)299* - delete arguments(n+1), ...300* NOTE that this might modify the input list.301*/302void handleVarArgs(List<Value> arguments)303throws ClassNotLoadedException, InvalidTypeException {304List<Type> paramTypes = this.argumentTypes();305ArrayType lastParamType = (ArrayType)paramTypes.get(paramTypes.size() - 1);306int argCount = arguments.size();307int paramCount = paramTypes.size();308if (argCount < paramCount - 1) {309// Error; will be caught later.310return;311}312if (argCount == paramCount - 1) {313// It is ok to pass 0 args to the var arg.314// We have to gen a 0 length array.315ArrayReference argArray = lastParamType.newInstance(0);316arguments.add(argArray);317return;318}319Value nthArgValue = arguments.get(paramCount - 1);320if (nthArgValue == null && argCount == paramCount) {321// We have one varargs parameter and it is null322// so we don't have to do anything.323return;324}325// If the first varargs parameter is null, then don't326// access its type since it can't be an array.327Type nthArgType = (nthArgValue == null) ? null : nthArgValue.type();328if (nthArgType instanceof ArrayTypeImpl) {329if (argCount == paramCount &&330((ArrayTypeImpl)nthArgType).isAssignableTo(lastParamType)) {331/*332* This is case 1. A compatible array is being passed to the333* var args array param. We don't have to do anything.334*/335return;336}337}338339/*340* Case 2. We have to verify that the n, n+1, ... args are compatible341* with componentType, and do conversions if necessary and create342* an array of componentType to hold these possibly converted values.343*/344int count = argCount - paramCount + 1;345ArrayReference argArray = lastParamType.newInstance(count);346347/*348* This will copy arguments(paramCount - 1) ... to argArray(0) ...349* doing whatever conversions are needed! It will throw an350* exception if an incompatible arg is encountered351*/352argArray.setValues(0, arguments, paramCount - 1, count);353arguments.set(paramCount - 1, argArray);354355/*356* Remove the excess args357*/358for (int ii = paramCount; ii < argCount; ii++) {359arguments.remove(paramCount);360}361return;362}363364/*365* The output list will be different than the input list.366*/367List<Value> validateAndPrepareArgumentsForInvoke(List<? extends Value> origArguments)368throws ClassNotLoadedException, InvalidTypeException {369370List<Value> arguments = new ArrayList<>(origArguments);371if (isVarArgs()) {372handleVarArgs(arguments);373}374375int argSize = arguments.size();376377JNITypeParser parser = new JNITypeParser(signature());378List<String> signatures = parser.argumentSignatures();379380if (signatures.size() != argSize) {381throw new IllegalArgumentException("Invalid argument count: expected " +382signatures.size() + ", received " +383arguments.size());384}385386for (int i = 0; i < argSize; i++) {387Value value = arguments.get(i);388value = ValueImpl.prepareForAssignment(value,389new ArgumentContainer(i));390arguments.set(i, value);391}392return arguments;393}394395public String toString() {396StringBuilder sb = new StringBuilder();397sb.append(declaringType().name());398sb.append(".");399sb.append(name());400sb.append("(");401boolean first = true;402for (String name : argumentTypeNames()) {403if (!first) {404sb.append(", ");405}406sb.append(name);407first = false;408}409sb.append(")");410return sb.toString();411}412}413414415