lvalue.java
来自「jpda例子文件」· Java 代码 · 共 1,049 行 · 第 1/3 页
JAVA
1,049 行
interfaces = ((ClassType)fromType).interfaces(); } else { // fromType must be an InterfaceType interfaces = ((InterfaceType)fromType).superinterfaces(); } Iterator iter = interfaces.iterator(); while (iter.hasNext()) { InterfaceType interfaze = (InterfaceType)iter.next(); if (isAssignableTo(interfaze, toType)) { return true; } } return false; } static Method resolveOverload(List overloads, List arguments) throws ParseException { // If there is only one method to call, we'll just choose // that without looking at the args. If they aren't right // the invoke will return a better error message than we // could generate here. if (overloads.size() == 1) { return (Method)overloads.get(0); } // Resolving overloads is beyond the scope of this exercise. // So, we will look for a method that matches exactly the // types of the arguments. If we can't find one, then // if there is exactly one method whose param types are assignable // from the arg types, we will use that. Otherwise, // it is an error. We won't guess which of multiple possible // methods to call. And, since casts aren't implemented, // the user can't use them to pick a particular overload to call. // IE, the user is out of luck in this case. Iterator iter = overloads.iterator(); Method retVal = null; int assignableCount = 0; while (iter.hasNext()) { Method mm = (Method)iter.next(); List argTypes; try { argTypes = mm.argumentTypes(); } catch (ClassNotLoadedException ee) { // This probably won't happen for the // method that we are really supposed to // call. continue; } int compare = argumentsMatch(argTypes, arguments); if (compare == SAME) { return mm; } if (compare == DIFFERENT) { continue; } // Else, it is assignable. Remember it. retVal = mm; assignableCount++; } // At this point, we didn't find an exact match, // but we found one for which the args are assignable. // if (retVal != null) { if (assignableCount == 1) { return retVal; } throw new ParseException("Arguments match multiple methods"); } throw new ParseException("Arguments match no method"); } private static class LValueLocal extends LValue { final StackFrame frame; final LocalVariable var; LValueLocal(StackFrame frame, LocalVariable var) { this.frame = frame; this.var = var; } Value getValue() { if (jdiValue == null) { jdiValue = frame.getValue(var); } return jdiValue; } void setValue0(Value val) throws InvalidTypeException, ClassNotLoadedException { frame.setValue(var, val); jdiValue = val; } void invokeWith(List arguments) throws ParseException { throw new ParseException(var.name() + " is not a method"); } } private static class LValueInstanceMember extends LValue { final ObjectReference obj; final ThreadReference thread; final Field matchingField; final List overloads; Method matchingMethod = null; List methodArguments = null; LValueInstanceMember(Value value, String memberName, ThreadReference thread) throws ParseException { if (!(value instanceof ObjectReference)) { throw new ParseException( "Cannot access field of primitive type: " + value); } this.obj = (ObjectReference)value; this.thread = thread; ReferenceType refType = obj.referenceType(); /* * Can't tell yet whether this LValue will be accessed as a * field or method, so we keep track of all the possibilities */ matchingField = LValue.fieldByName(refType, memberName, LValue.INSTANCE); overloads = LValue.methodsByName(refType, memberName, LValue.INSTANCE); if ((matchingField == null) && overloads.size() == 0) { throw new ParseException("No instance field or method with the name " + memberName + " in " + refType.name()); } } Value getValue() throws InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, ParseException { if (jdiValue != null) { return jdiValue; } if (matchingMethod == null) { if (matchingField == null) { throw new ParseException("No such field in " + obj.referenceType().name()); } return jdiValue = obj.getValue(matchingField); } else { return jdiValue = obj.invokeMethod(thread, matchingMethod, methodArguments, 0); } } void setValue0(Value val) throws ParseException, InvalidTypeException, ClassNotLoadedException { if (matchingMethod != null) { throw new ParseException("Cannot assign to a method invocation"); } obj.setValue(matchingField, val); jdiValue = val; } void invokeWith(List arguments) throws ParseException { if (matchingMethod != null) { throw new ParseException("Invalid consecutive invocations"); } methodArguments = arguments; matchingMethod = LValue.resolveOverload(overloads, arguments); } } private static class LValueStaticMember extends LValue { final ReferenceType refType; final ThreadReference thread; final Field matchingField; final List overloads; Method matchingMethod = null; List methodArguments = null; LValueStaticMember(ReferenceType refType, String memberName, ThreadReference thread) throws ParseException { this.refType = refType; this.thread = thread; /* * Can't tell yet whether this LValue will be accessed as a * field or method, so we keep track of all the possibilities */ matchingField = LValue.fieldByName(refType, memberName, LValue.STATIC); overloads = LValue.methodsByName(refType, memberName, LValue.STATIC); if ((matchingField == null) && overloads.size() == 0) { throw new ParseException("No static field or method with the name " + memberName + " in " + refType.name()); } } Value getValue() throws InvocationException, InvalidTypeException, ClassNotLoadedException, IncompatibleThreadStateException, ParseException { if (jdiValue != null) { return jdiValue; } if (matchingMethod == null) { return jdiValue = refType.getValue(matchingField); } else if (refType instanceof ClassType) { ClassType clazz = (ClassType)refType; return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0); } else { throw new InvalidTypeException("Cannot invoke static method on " + refType.name()); } } void setValue0(Value val) throws ParseException, InvalidTypeException, ClassNotLoadedException { if (matchingMethod != null) { throw new ParseException("Cannot assign to a method invocation"); } if (!(refType instanceof ClassType)) { throw new ParseException( "Cannot set interface field: " + refType); } ((ClassType)refType).setValue(matchingField, val); jdiValue = val; } void invokeWith(List arguments) throws ParseException { if (matchingMethod != null) { throw new ParseException("Invalid consecutive invocations"); } methodArguments = arguments; matchingMethod = LValue.resolveOverload(overloads, arguments); } } private static class LValueArrayLength extends LValue { /* * Since one can code "int myLen = myArray.length;", * one might expect that these JDI calls would get a Value * object for the length of an array in the debugee: * Field xxx = ArrayType.fieldByName("length") * Value lenVal= ArrayReference.getValue(xxx) * * However, this doesn't work because the array length isn't * really stored as a field, and can't be accessed as such * via JDI. Instead, the arrayRef.length() method has to be * used. */ final ArrayReference arrayRef; LValueArrayLength (ArrayReference value) { this.arrayRef = value; } Value getValue() { if (jdiValue == null) { jdiValue = arrayRef.virtualMachine().mirrorOf(arrayRef.length()); } return jdiValue; } void setValue0(Value value) throws ParseException { throw new ParseException("Cannot set constant: " + value); } void invokeWith(List arguments) throws ParseException { throw new ParseException("Array element is not a method"); } } private static class LValueArrayElement extends LValue { final ArrayReference array; final int index; LValueArrayElement(Value value, int index) throws ParseException { if (!(value instanceof ArrayReference)) { throw new ParseException( "Must be array type: " + value); } this.array = (ArrayReference)value; this.index = index; } Value getValue() { if (jdiValue == null) { jdiValue = array.getValue(index); } return jdiValue; } void setValue0(Value val) throws InvalidTypeException, ClassNotLoadedException { array.setValue(index, val); jdiValue = val; } void invokeWith(List arguments) throws ParseException { throw new ParseException("Array element is not a method"); } } private static class LValueConstant extends LValue { final Value value; LValueConstant(Value value) { this.value = value; } Value getValue() { if (jdiValue == null) { jdiValue = value; } return jdiValue; } void setValue0(Value val) throws ParseException { throw new ParseException("Cannot set constant: " + value); } void invokeWith(List arguments) throws ParseException { throw new ParseException("Constant is not a method"); } } static LValue make(VirtualMachine vm, boolean val) { return new LValueConstant(vm.mirrorOf(val)); } static LValue make(VirtualMachine vm, byte val) { return new LValueConstant(vm.mirrorOf(val)); } static LValue make(VirtualMachine vm, char val) { return new LValueConstant(vm.mirrorOf(val)); } static LValue make(VirtualMachine vm, short val) { return new LValueConstant(vm.mirrorOf(val)); } static LValue make(VirtualMachine vm, int val) { return new LValueConstant(vm.mirrorOf(val)); } static LValue make(VirtualMachine vm, long val) { return new LValueConstant(vm.mirrorOf(val)); } static LValue make(VirtualMachine vm, float val) { return new LValueConstant(vm.mirrorOf(val)); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?