Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/tools/jdi/ArrayReferenceImpl.java
38920 views
/*1* Copyright (c) 1998, 2011, 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 com.sun.jdi.*;2829import java.util.List;30import java.util.ArrayList;31import java.util.Arrays;32import java.util.Iterator;3334public class ArrayReferenceImpl extends ObjectReferenceImpl35implements ArrayReference36{37int length = -1;3839ArrayReferenceImpl(VirtualMachine aVm,long aRef) {40super(aVm,aRef);41}4243protected ClassTypeImpl invokableReferenceType(Method method) {44// The method has to be a method on Object since45// arrays don't have methods nor any other 'superclasses'46// So, use the ClassTypeImpl for Object instead of47// the ArrayTypeImpl for the array itself.48return (ClassTypeImpl)method.declaringType();49}5051ArrayTypeImpl arrayType() {52return (ArrayTypeImpl)type();53}5455/**56* Return array length.57* Need not be synchronized since it cannot be provably stale.58*/59public int length() {60if(length == -1) {61try {62length = JDWP.ArrayReference.Length.63process(vm, this).arrayLength;64} catch (JDWPException exc) {65throw exc.toJDIException();66}67}68return length;69}7071public Value getValue(int index) {72List<Value> list = getValues(index, 1);73return list.get(0);74}7576public List<Value> getValues() {77return getValues(0, -1);78}7980/**81* Validate that the range to set/get is valid.82* length of -1 (meaning rest of array) has been converted83* before entry.84*/85private void validateArrayAccess(int index, int length) {86// because length can be computed from index,87// index must be tested first for correct error message88if ((index < 0) || (index > length())) {89throw new IndexOutOfBoundsException(90"Invalid array index: " + index);91}92if (length < 0) {93throw new IndexOutOfBoundsException(94"Invalid array range length: " + length);95}96if (index + length > length()) {97throw new IndexOutOfBoundsException(98"Invalid array range: " +99index + " to " + (index + length - 1));100}101}102103@SuppressWarnings("unchecked")104private static <T> T cast(Object x) {105return (T)x;106}107108public List<Value> getValues(int index, int length) {109if (length == -1) { // -1 means the rest of the array110length = length() - index;111}112validateArrayAccess(index, length);113if (length == 0) {114return new ArrayList<Value>();115}116117List<Value> vals;118try {119vals = cast(JDWP.ArrayReference.GetValues.process(vm, this, index, length).values);120} catch (JDWPException exc) {121throw exc.toJDIException();122}123124return vals;125}126127public void setValue(int index, Value value)128throws InvalidTypeException,129ClassNotLoadedException {130List<Value> list = new ArrayList<Value>(1);131list.add(value);132setValues(index, list, 0, 1);133}134135public void setValues(List<? extends Value> values)136throws InvalidTypeException,137ClassNotLoadedException {138setValues(0, values, 0, -1);139}140141public void setValues(int index, List<? extends Value> values,142int srcIndex, int length)143throws InvalidTypeException,144ClassNotLoadedException {145146if (length == -1) { // -1 means the rest of the array147// shorter of, the rest of the array and rest of148// the source values149length = Math.min(length() - index,150values.size() - srcIndex);151}152validateMirrorsOrNulls(values);153validateArrayAccess(index, length);154155if ((srcIndex < 0) || (srcIndex > values.size())) {156throw new IndexOutOfBoundsException(157"Invalid source index: " + srcIndex);158}159if (srcIndex + length > values.size()) {160throw new IndexOutOfBoundsException(161"Invalid source range: " +162srcIndex + " to " +163(srcIndex + length - 1));164}165166boolean somethingToSet = false;;167ValueImpl[] setValues = new ValueImpl[length];168169for (int i = 0; i < length; i++) {170ValueImpl value = (ValueImpl)values.get(srcIndex + i);171172try {173// Validate and convert if necessary174setValues[i] =175ValueImpl.prepareForAssignment(value,176new Component());177somethingToSet = true;178} catch (ClassNotLoadedException e) {179/*180* Since we got this exception,181* the component must be a reference type.182* This means the class has not yet been loaded183* through the defining class's class loader.184* If the value we're trying to set is null,185* then setting to null is essentially a186* no-op, and we should allow it without an187* exception.188*/189if (value != null) {190throw e;191}192}193}194if (somethingToSet) {195try {196JDWP.ArrayReference.SetValues.197process(vm, this, index, setValues);198} catch (JDWPException exc) {199throw exc.toJDIException();200}201}202}203204public String toString() {205return "instance of " + arrayType().componentTypeName() +206"[" + length() + "] (id=" + uniqueID() + ")";207}208209byte typeValueKey() {210return JDWP.Tag.ARRAY;211}212213void validateAssignment(ValueContainer destination)214throws InvalidTypeException, ClassNotLoadedException {215try {216super.validateAssignment(destination);217} catch (ClassNotLoadedException e) {218/*219* An array can be used extensively without the220* enclosing loader being recorded by the VM as an221* initiating loader of the array type. In addition, the222* load of an array class is fairly harmless as long as223* the component class is already loaded. So we relax the224* rules a bit and allow the assignment as long as the225* ultimate component types are assignable.226*/227boolean valid = false;228JNITypeParser destParser = new JNITypeParser(229destination.signature());230JNITypeParser srcParser = new JNITypeParser(231arrayType().signature());232int destDims = destParser.dimensionCount();233if (destDims <= srcParser.dimensionCount()) {234/*235* Remove all dimensions from the destination. Remove236* the same number of dimensions from the source.237* Get types for both and check to see if they are238* compatible.239*/240String destComponentSignature =241destParser.componentSignature(destDims);242Type destComponentType =243destination.findType(destComponentSignature);244String srcComponentSignature =245srcParser.componentSignature(destDims);246Type srcComponentType =247arrayType().findComponentType(srcComponentSignature);248valid = ArrayTypeImpl.isComponentAssignable(destComponentType,249srcComponentType);250}251252if (!valid) {253throw new InvalidTypeException("Cannot assign " +254arrayType().name() +255" to " +256destination.typeName());257}258}259}260261/*262* Represents an array component to other internal parts of this263* implementation. This is not exposed at the JDI level. Currently,264* this class is needed only for type checking so it does not even265* reference a particular component - just a generic component266* of this array. In the future we may need to expand its use.267*/268class Component implements ValueContainer {269public Type type() throws ClassNotLoadedException {270return arrayType().componentType();271}272public String typeName() {273return arrayType().componentTypeName();274}275public String signature() {276return arrayType().componentSignature();277}278public Type findType(String signature) throws ClassNotLoadedException {279return arrayType().findComponentType(signature);280}281}282}283284285