lvalue.java

来自「jpda例子文件」· Java 代码 · 共 1,049 行 · 第 1/3 页

JAVA
1,049
字号
/* * @(#)LValue.java	1.24 02/09/05 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//* * Copyright (c) 1997-1999 by Sun Microsystems, Inc. All Rights Reserved. *  * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. *  * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. *  * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */package com.sun.tools.example.debug.expr;import com.sun.jdi.*;import java.util.*;abstract class LValue {    // The JDI Value object for this LValue.  Once we have this Value,    // we have to remember it since after we return the LValue object    // to the ExpressionParser, it might decide that it needs     // the 'toString' value for the LValue in which case it will    // call getMassagedValue to get this toString value.  At that    // point, we don't want to call JDI a 2nd time to get the Value    // for the LValue.  This is especially wrong when the LValue    // represents a member function.  We would end up calling it    // a 2nd time.    //    // Unfortunately, there are several levels of calls to    // get/set values in this file.  To minimize confusion,    // jdiValue is set/tested at the lowest level - right    // next to the actual calls to JDI methods to get/set the    // value in the debuggee.      protected Value jdiValue;    abstract Value getValue() throws InvocationException,                                      IncompatibleThreadStateException,                                     InvalidTypeException,                                     ClassNotLoadedException,                                     ParseException;    abstract void setValue0(Value value)                    throws ParseException, InvalidTypeException,                           ClassNotLoadedException;    abstract void invokeWith(List arguments) throws ParseException;    void setValue(Value value) throws ParseException {        try {            setValue0(value);        } catch (InvalidTypeException exc) {            throw new ParseException(                "Attempt to set value of incorrect type" +                exc);        } catch (ClassNotLoadedException exc) {            throw new ParseException(                "Attempt to set value before " + exc.className() + " was loaded" +                exc);        }    }            void setValue(LValue lval) throws ParseException {        setValue(lval.interiorGetValue());    }    LValue memberLValue(ExpressionParser.GetFrame frameGetter,                         String fieldName) throws ParseException {        try {            return memberLValue(fieldName, frameGetter.get().thread());        } catch (IncompatibleThreadStateException exc) {            throw new ParseException("Thread not suspended");        }    }    LValue memberLValue(String fieldName, ThreadReference thread) throws ParseException {                Value val = interiorGetValue();        if ((val instanceof ArrayReference) &&            "length".equals(fieldName)){            return new LValueArrayLength((ArrayReference)val);        }        return new LValueInstanceMember(val, fieldName, thread);    }    // Return the Value for this LValue that would be used to concatenate    // to a String.  IE, if it is an Object, call toString in the debuggee.    Value getMassagedValue(ExpressionParser.GetFrame frameGetter) throws ParseException {        Value vv = interiorGetValue();        // If vv is an ObjectReference, then we have to        // do the implicit call to toString().        if (vv instanceof ObjectReference &&            !(vv instanceof StringReference) &&             !(vv instanceof ArrayReference)) {            StackFrame frame;            try {                frame = frameGetter.get();            } catch (IncompatibleThreadStateException exc) {                throw new ParseException("Thread not suspended");            }            ThreadReference thread = frame.thread();            LValue toStringMember = memberLValue("toString", thread);            toStringMember.invokeWith(new ArrayList());            return toStringMember.interiorGetValue();        }        return vv;    }    Value interiorGetValue() throws ParseException {        Value value;        try {            value = getValue();        } catch (InvocationException e) {            throw new ParseException("Unable to complete expression. Exception " +                                     e.exception() + " thrown");        } catch (IncompatibleThreadStateException itse) {            throw new ParseException("Unable to complete expression. Thread " +                                     "not suspended for method invoke");        } catch (InvalidTypeException ite) {            throw new ParseException("Unable to complete expression. Method " +                                     "argument type mismatch");        } catch (ClassNotLoadedException tnle) {            throw new ParseException("Unable to complete expression. Method " +                                     "argument type " + tnle.className() +                                      " not yet loaded");        }        return value;    }    LValue arrayElementLValue(LValue lval) throws ParseException {        Value indexValue = lval.interiorGetValue();        int index;        if ( (indexValue instanceof IntegerValue) ||             (indexValue instanceof ShortValue) ||             (indexValue instanceof ByteValue) ||             (indexValue instanceof CharValue) ) {            index = ((PrimitiveValue)indexValue).intValue();        } else {            throw new ParseException("Array index must be a integer type");        }        return new LValueArrayElement(interiorGetValue(), index);    }    public String toString() {        try {            return interiorGetValue().toString();        } catch (ParseException e) {            return "<Parse Exception>";        }    }    static final int STATIC = 0;    static final int INSTANCE = 1;    static Field fieldByName(ReferenceType refType, String name, int kind) {        /*         * TO DO: Note that this currently fails to find superclass         * or implemented interface fields. This is due to a temporary         * limititation of RefType.fieldByName. Once that method is          * fixed, superclass fields will be found.         */        Field field = refType.fieldByName(name);        if (field != null) {            boolean isStatic = field.isStatic();            if (((kind == STATIC) && !isStatic) ||                 ((kind == INSTANCE) && isStatic)) {                field = null;            }        }/***        System.err.println("fieldByName: " + refType.name() + " " +                                             name + " " +                                             kind + " " +                                              (field != null));***/        return field;    }    static List methodsByName(ReferenceType refType, String name, int kind) {        List list = refType.methodsByName(name);        Iterator iter = list.iterator();        while (iter.hasNext()) {            Method method = (Method)iter.next();            boolean isStatic = method.isStatic();            if (((kind == STATIC) && !isStatic) ||                 ((kind == INSTANCE) && isStatic)) {                iter.remove();            }        }        return list;    }    static List primitiveTypeNames = new ArrayList();    static {        primitiveTypeNames.add("boolean");        primitiveTypeNames.add("byte");        primitiveTypeNames.add("char");        primitiveTypeNames.add("short");        primitiveTypeNames.add("int");        primitiveTypeNames.add("long");        primitiveTypeNames.add("float");        primitiveTypeNames.add("double");    }    static final int SAME = 0;    static final int ASSIGNABLE = 1;    static final int DIFFERENT = 2;    /*     * Return SAME, DIFFERENT or ASSIGNABLE.     * SAME means each arg type is the same as type of the corr. arg.     * ASSIGNABLE means that not all the pairs are the same, but     * for those that aren't, at least the argType is assignable     * from the type of the argument value.     * DIFFERENT means that in at least one pair, the     * argType is not assignable from the type of the argument value.     * IE, one is an Apple and the other is an Orange.     */    static int argumentsMatch(List argTypes, List arguments) {        if (argTypes.size() != arguments.size()) {            return DIFFERENT;        }        Iterator typeIter = argTypes.iterator();        Iterator valIter = arguments.iterator();        int result = SAME;        // If any pair aren't the same, change the        // result to ASSIGNABLE.  If any pair aren't        // assignable, return DIFFERENT        while (typeIter.hasNext()) {            Type argType = (Type)typeIter.next();            Value value = (Value)valIter.next();            if (value == null) {                // Null values can be passed to any non-primitive argument                if (primitiveTypeNames.contains(argType.name())) {                    return DIFFERENT;                }                // Else, we will assume that a null value                // exactly matches an object type.            }            if (!value.type().equals(argType)) {                if (isAssignableTo(value.type(), argType)) {                    result = ASSIGNABLE;                } else {                    return DIFFERENT;                }            }        }        return result;    }    // These is...AssignableTo methods are based on similar code in the JDI    // implementations of ClassType, ArrayType, and InterfaceType    static boolean isComponentAssignable(Type fromType, Type toType) {        if (fromType instanceof PrimitiveType) {            // Assignment of primitive arrays requires identical            // component types.            return fromType.equals(toType);        }        if (toType instanceof PrimitiveType) {            return false;        }        // Assignment of object arrays requires availability        // of widening conversion of component types        return isAssignableTo(fromType, toType);    }    static boolean isArrayAssignableTo(ArrayType fromType, Type toType) {        if (toType instanceof ArrayType) {            try {                Type toComponentType = ((ArrayType)toType).componentType();                return isComponentAssignable(fromType.componentType(), toComponentType);            } catch (ClassNotLoadedException e) {                // One or both component types has not yet been                 // loaded => can't assign                return false;            }        }        if (toType instanceof InterfaceType) {            // Only valid InterfaceType assignee is Cloneable            return toType.name().equals("java.lang.Cloneable");        }         // Only valid ClassType assignee is Object        return toType.name().equals("java.lang.Object");    }    static boolean isAssignableTo(Type fromType, Type toType) {        if (fromType.equals(toType)) {            return true;        }        // If one is boolean, so must be the other.        if (fromType instanceof BooleanType) {            if (toType instanceof BooleanType) {                return true;            }            return false;        }        if (toType instanceof BooleanType) {            return false;        }        // Other primitive types are intermixable only with each other.        if (fromType instanceof PrimitiveType) {            if (toType instanceof PrimitiveType) {                return true;            }            return false;        }         if (toType instanceof PrimitiveType) {            return false;        }        // neither one is primitive.        if (fromType instanceof ArrayType) {            return isArrayAssignableTo((ArrayType)fromType, toType);        }        List interfaces;        if (fromType instanceof ClassType) {            ClassType superclazz = ((ClassType)fromType).superclass();            if ((superclazz != null) && isAssignableTo(superclazz, toType)) {                return true;            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?