Diff
checker
Text
Text
Images
Documents
Excel
Folders
Legal
Enterprise
Desktop
Pricing
Sign in
Download Diffchecker Desktop
Compare text
Find the difference between two text files
Tools
History
Real-time editor
Hide unchanged lines
Disable line wrap
Layout
Split
Unified
Diff precision
Smart
Word
Char
Syntax highlighting
Choose syntax
Ignore
Transform text
Go to first change
Edit input
Diffchecker Desktop
The most secure way to run Diffchecker. Get the Diffchecker Desktop app: your diffs never leave your computer!
Get Desktop
ArrayReferenceImpl
Created
6 years ago
Diff never expires
Clear
Export
Share
Explain
20 removals
Lines
Total
Removed
Characters
Total
Removed
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
284 lines
Copy
87 additions
Lines
Total
Added
Characters
Total
Added
To continue using this feature, upgrade to
Diff
checker
Pro
View Pricing
351 lines
Copy
/*
/*
Copy
Copied
Copy
Copied
* Copyright (c) 1998, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 201
7
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* by Oracle in the LICENSE file that accompanied this code.
*
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* accompanied this code).
*
*
* You should have received a copy of the GNU General Public License version
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* or visit www.oracle.com if you need additional information or have any
* questions.
* questions.
Copy
Copied
Copy
Copied
*
* Copyright (C) 2019 JetBrains s.r.o.
*
* This program is free software; you can redistribute and/or modify it under
* the terms of the GNU General Public License v2 with Classpath Exception.
* The text of the license is available in the file LICENSE.TXT.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.TXT for more details.
*
* You may contact JetBrains s.r.o. at Na Hřebenech II 1718/10, 140 00 Prague,
* Czech Republic or at legal@jetbrains.com.
*/
*/
Copy
Copied
Copy
Copied
package com.
sun.tools
.jdi;
package com.
jetbrains
.jdi;
import com.sun.jdi.*;
Copy
Copied
Copy
Copied
import java.util.Collections;
import java.util.List;
import java.util.List;
Copy
Copied
Copy
Copied
import java.util.
ArrayList;
import java.util.
concurrent.CompletableFuture;
import
java.util.Arrays
;
import
java.util.Iterator
;
import com.sun.jdi.ArrayReference;
import com.sun.jdi.ClassNotLoadedException;
import
com.sun.jdi.InvalidTypeException;
import com.sun.jdi.Method
;
import
com.sun.jdi.Type;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine
;
public class ArrayReferenceImpl extends ObjectReferenceImpl
public class ArrayReferenceImpl extends ObjectReferenceImpl
implements ArrayReference
implements ArrayReference
{
{
Copy
Copied
Copy
Copied
int length = -1;
private volatile
int length = -1;
Copy
Copied
Copy
Copied
ArrayReferenceImpl(VirtualMachine aVm,
long aRef) {
ArrayReferenceImpl(VirtualMachine aVm,
long aRef) {
super(aVm,
aRef);
super(aVm,
aRef);
}
}
protected ClassTypeImpl invokableReferenceType(Method method) {
protected ClassTypeImpl invokableReferenceType(Method method) {
// The method has to be a method on Object since
// The method has to be a method on Object since
// arrays don't have methods nor any other 'superclasses'
// arrays don't have methods nor any other 'superclasses'
// So, use the ClassTypeImpl for Object instead of
// So, use the ClassTypeImpl for Object instead of
// the ArrayTypeImpl for the array itself.
// the ArrayTypeImpl for the array itself.
return (ClassTypeImpl)method.declaringType();
return (ClassTypeImpl)method.declaringType();
}
}
ArrayTypeImpl arrayType() {
ArrayTypeImpl arrayType() {
return (ArrayTypeImpl)type();
return (ArrayTypeImpl)type();
}
}
/**
/**
* Return array length.
* Return array length.
* Need not be synchronized since it cannot be provably stale.
* Need not be synchronized since it cannot be provably stale.
*/
*/
public int length() {
public int length() {
if(length == -1) {
if(length == -1) {
try {
try {
length = JDWP.ArrayReference.Length.
length = JDWP.ArrayReference.Length.
process(vm, this).arrayLength;
process(vm, this).arrayLength;
} catch (JDWPException exc) {
} catch (JDWPException exc) {
throw exc.toJDIException();
throw exc.toJDIException();
}
}
}
}
return length;
return length;
}
}
Copy
Copied
Copy
Copied
public CompletableFuture<Integer> lengthAsync() {
if (length != -1) {
return CompletableFuture.completedFuture(length);
}
return JDWP.ArrayReference.Length.processAsync(vm, this).thenApply(r -> length = r.arrayLength);
}
void setLength(int length) {
this.length = length;
}
public Value getValue(int index) {
public Value getValue(int index) {
Copy
Copied
Copy
Copied
List<Value> list = getValues(index, 1);
return getValues(index, 1).get(0);
return list.get(0);
}
public CompletableFuture<Value> getValueAsync(int index) {
return getValuesAsync(index, 1).thenApply(r -> r.get(0));
}
}
public List<Value> getValues() {
public List<Value> getValues() {
return getValues(0, -1);
return getValues(0, -1);
}
}
Copy
Copied
Copy
Copied
public CompletableFuture<List<Value>> getValuesAsync() {
return getValuesAsync(0, -1);
}
/**
/**
* Validate that the range to set/get is valid.
* Validate that the range to set/get is valid.
* length of -1 (meaning rest of array) has been converted
* length of -1 (meaning rest of array) has been converted
* before entry.
* before entry.
*/
*/
private void validateArrayAccess(int index, int length) {
private void validateArrayAccess(int index, int length) {
// because length can be computed from index,
// because length can be computed from index,
// index must be tested first for correct error message
// index must be tested first for correct error message
if ((index < 0) || (index > length())) {
if ((index < 0) || (index > length())) {
throw new IndexOutOfBoundsException(
throw new IndexOutOfBoundsException(
"Invalid array index: " + index);
"Invalid array index: " + index);
}
}
if (length < 0) {
if (length < 0) {
throw new IndexOutOfBoundsException(
throw new IndexOutOfBoundsException(
"Invalid array range length: " + length);
"Invalid array range length: " + length);
}
}
if (index + length > length()) {
if (index + length > length()) {
throw new IndexOutOfBoundsException(
throw new IndexOutOfBoundsException(
"Invalid array range: " +
"Invalid array range: " +
index + " to " + (index + length - 1));
index + " to " + (index + length - 1));
}
}
}
}
@SuppressWarnings("unchecked")
@SuppressWarnings("unchecked")
private static <T> T cast(Object x) {
private static <T> T cast(Object x) {
return (T)x;
return (T)x;
}
}
Copy
Copied
Copy
Copied
public CompletableFuture<List<Value>> getValuesAsync(int index, int len) {
return lengthAsync().thenCompose(__ -> { // preload length
int length = len;
if (length == -1) { // -1 means the rest of the array
length = length() - index;
}
validateArrayAccess(index, length);
if (length == 0) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
return JDWP.ArrayReference.GetValues.processAsync(vm, this, index, length)
.thenApply(r -> cast(r.values));
});
}
public List<Value> getValues(int index, int length) {
public List<Value> getValues(int index, int length) {
if (length == -1) { // -1 means the rest of the array
if (length == -1) { // -1 means the rest of the array
length = length() - index;
length = length() - index;
}
}
validateArrayAccess(index, length);
validateArrayAccess(index, length);
if (length == 0) {
if (length == 0) {
Copy
Copied
Copy
Copied
return
new ArrayList<Value>
();
return
Collections.emptyList
();
}
}
List<Value> vals;
List<Value> vals;
try {
try {
vals = cast(JDWP.ArrayReference.GetValues.process(vm, this, index, length).values);
vals = cast(JDWP.ArrayReference.GetValues.process(vm, this, index, length).values);
} catch (JDWPException exc) {
} catch (JDWPException exc) {
throw exc.toJDIException();
throw exc.toJDIException();
}
}
return vals;
return vals;
}
}
public void setValue(int index, Value value)
public void setValue(int index, Value value)
throws InvalidTypeException,
throws InvalidTypeException,
ClassNotLoadedException {
ClassNotLoadedException {
Copy
Copied
Copy
Copied
List<Value> list = new ArrayList<Value>(1);
setValues(index,
Collections.singletonList(value)
, 0, 1);
list.add(value);
setValues(index,
list
, 0, 1);
}
}
public void setValues(List<? extends Value> values)
public void setValues(List<? extends Value> values)
throws InvalidTypeException,
throws InvalidTypeException,
ClassNotLoadedException {
ClassNotLoadedException {
setValues(0, values, 0, -1);
setValues(0, values, 0, -1);
}
}
public void setValues(int index, List<? extends Value> values,
public void setValues(int index, List<? extends Value> values,
int srcIndex, int length)
int srcIndex, int length)
throws InvalidTypeException,
throws InvalidTypeException,
Copy
Copied
Copy
Copied
ClassNotLoadedException {
setValues(index, values, srcIndex, length, true);
}
public void setValues(int index, List<? extends Value> values,
int srcIndex, int length, boolean checkAssignable)
throws InvalidTypeException,
ClassNotLoadedException {
ClassNotLoadedException {
if (length == -1) { // -1 means the rest of the array
if (length == -1) { // -1 means the rest of the array
// shorter of, the rest of the array and rest of
// shorter of, the rest of the array and rest of
// the source values
// the source values
length = Math.min(length() - index,
length = Math.min(length() - index,
values.size() - srcIndex);
values.size() - srcIndex);
}
}
validateMirrorsOrNulls(values);
validateMirrorsOrNulls(values);
validateArrayAccess(index, length);
validateArrayAccess(index, length);
if ((srcIndex < 0) || (srcIndex > values.size())) {
if ((srcIndex < 0) || (srcIndex > values.size())) {
throw new IndexOutOfBoundsException(
throw new IndexOutOfBoundsException(
"Invalid source index: " + srcIndex);
"Invalid source index: " + srcIndex);
}
}
if (srcIndex + length > values.size()) {
if (srcIndex + length > values.size()) {
throw new IndexOutOfBoundsException(
throw new IndexOutOfBoundsException(
"Invalid source range: " +
"Invalid source range: " +
srcIndex + " to " +
srcIndex + " to " +
(srcIndex + length - 1));
(srcIndex + length - 1));
}
}
Copy
Copied
Copy
Copied
boolean somethingToSet = false;
;
boolean somethingToSet = false;
ValueImpl[] setValues = new ValueImpl[length];
ValueImpl[] setValues = new ValueImpl[length];
for (int i = 0; i < length; i++) {
for (int i = 0; i < length; i++) {
ValueImpl value = (ValueImpl)values.get(srcIndex + i);
ValueImpl value = (ValueImpl)values.get(srcIndex + i);
try {
try {
// Validate and convert if necessary
// Validate and convert if necessary
Copy
Copied
Copy
Copied
setValues[i] =
setValues[i] =
prepareForAssignment(value,
new Component(
checkAssignable
));
ValueImpl.
prepareForAssignment(value,
new Component(
));
somethingToSet = true;
somethingToSet = true;
} catch (ClassNotLoadedException e) {
} catch (ClassNotLoadedException e) {
/*
/*
* Since we got this exception,
* Since we got this exception,
* the component must be a reference type.
* the component must be a reference type.
* This means the class has not yet been loaded
* This means the class has not yet been loaded
* through the defining class's class loader.
* through the defining class's class loader.
* If the value we're trying to set is null,
* If the value we're trying to set is null,
* then setting to null is essentially a
* then setting to null is essentially a
* no-op, and we should allow it without an
* no-op, and we should allow it without an
* exception.
* exception.
*/
*/
if (value != null) {
if (value != null) {
throw e;
throw e;
}
}
}
}
}
}
if (somethingToSet) {
if (somethingToSet) {
try {
try {
JDWP.ArrayReference.SetValues.
JDWP.ArrayReference.SetValues.
process(vm, this, index, setValues);
process(vm, this, index, setValues);
} catch (JDWPException exc) {
} catch (JDWPException exc) {
throw exc.toJDIException();
throw exc.toJDIException();
}
}
}
}
}
}
public String toString() {
public String toString() {
return "instance of " + arrayType().componentTypeName() +
return "instance of " + arrayType().componentTypeName() +
"[" + length() + "] (id=" + uniqueID() + ")";
"[" + length() + "] (id=" + uniqueID() + ")";
}
}
byte typeValueKey() {
byte typeValueKey() {
return JDWP.Tag.ARRAY;
return JDWP.Tag.ARRAY;
}
}
void validateAssignment(ValueContainer destination)
void validateAssignment(ValueContainer destination)
throws InvalidTypeException, ClassNotLoadedException {
throws InvalidTypeException, ClassNotLoadedException {
try {
try {
super.validateAssignment(destination);
super.validateAssignment(destination);
} catch (ClassNotLoadedException e) {
} catch (ClassNotLoadedException e) {
/*
/*
* An array can be used extensively without the
* An array can be used extensively without the
* enclosing loader being recorded by the VM as an
* enclosing loader being recorded by the VM as an
* initiating loader of the array type. In addition, the
* initiating loader of the array type. In addition, the
* load of an array class is fairly harmless as long as
* load of an array class is fairly harmless as long as
* the component class is already loaded. So we relax the
* the component class is already loaded. So we relax the
* rules a bit and allow the assignment as long as the
* rules a bit and allow the assignment as long as the
* ultimate component types are assignable.
* ultimate component types are assignable.
*/
*/
boolean valid = false;
boolean valid = false;
JNITypeParser destParser = new JNITypeParser(
JNITypeParser destParser = new JNITypeParser(
destination.signature());
destination.signature());
JNITypeParser srcParser = new JNITypeParser(
JNITypeParser srcParser = new JNITypeParser(
arrayType().signature());
arrayType().signature());
int destDims = destParser.dimensionCount();
int destDims = destParser.dimensionCount();
if (destDims <= srcParser.dimensionCount()) {
if (destDims <= srcParser.dimensionCount()) {
/*
/*
* Remove all dimensions from the destination. Remove
* Remove all dimensions from the destination. Remove
* the same number of dimensions from the source.
* the same number of dimensions from the source.
* Get types for both and check to see if they are
* Get types for both and check to see if they are
* compatible.
* compatible.
*/
*/
String destComponentSignature =
String destComponentSignature =
destParser.componentSignature(destDims);
destParser.componentSignature(destDims);
Type destComponentType =
Type destComponentType =
destination.findType(destComponentSignature);
destination.findType(destComponentSignature);
String srcComponentSignature =
String srcComponentSignature =
srcParser.componentSignature(destDims);
srcParser.componentSignature(destDims);
Type srcComponentType =
Type srcComponentType =
arrayType().findComponentType(srcComponentSignature);
arrayType().findComponentType(srcComponentSignature);
valid = ArrayTypeImpl.isComponentAssignable(destComponentType,
valid = ArrayTypeImpl.isComponentAssignable(destComponentType,
srcComponentType);
srcComponentType);
}
}
if (!valid) {
if (!valid) {
throw new InvalidTypeException("Cannot assign " +
throw new InvalidTypeException("Cannot assign " +
arrayType().name() +
arrayType().name() +
" to " +
" to " +
destination.typeName());
destination.typeName());
}
}
}
}
}
}
/*
/*
* Represents an array component to other internal parts of this
* Represents an array component to other internal parts of this
* implementation. This is not exposed at the JDI level. Currently,
* implementation. This is not exposed at the JDI level. Currently,
* this class is needed only for type checking so it does not even
* this class is needed only for type checking so it does not even
* reference a particular component - just a generic component
* reference a particular component - just a generic component
* of this array. In the future we may need to expand its use.
* of this array. In the future we may need to expand its use.
*/
*/
class Component implements ValueContainer {
class Component implements ValueContainer {
Copy
Copied
Copy
Copied
private final boolean checkAssignable;
public Component(boolean checkAssignable) {
super();
this.checkAssignable = checkAssignable;
}
public Type type() throws ClassNotLoadedException {
public Type type() throws ClassNotLoadedException {
return arrayType().componentType();
return arrayType().componentType();
}
}
public String typeName() {
public String typeName() {
return arrayType().componentTypeName();
return arrayType().componentTypeName();
}
}
public String signature() {
public String signature() {
return arrayType().componentSignature();
return arrayType().componentSignature();
}
}
public Type findType(String signature) throws ClassNotLoadedException {
public Type findType(String signature) throws ClassNotLoadedException {
return arrayType().findComponentType(signature);
return arrayType().findComponentType(signature);
}
}
Copy
Copied
Copy
Copied
@Override
public boolean checkAssignable() {
return checkAssignable;
}
}
}
}
}
Saved diffs
Original text
Open file
/* * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.jdi; import com.sun.jdi.*; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; public class ArrayReferenceImpl extends ObjectReferenceImpl implements ArrayReference { int length = -1; ArrayReferenceImpl(VirtualMachine aVm,long aRef) { super(aVm,aRef); } protected ClassTypeImpl invokableReferenceType(Method method) { // The method has to be a method on Object since // arrays don't have methods nor any other 'superclasses' // So, use the ClassTypeImpl for Object instead of // the ArrayTypeImpl for the array itself. return (ClassTypeImpl)method.declaringType(); } ArrayTypeImpl arrayType() { return (ArrayTypeImpl)type(); } /** * Return array length. * Need not be synchronized since it cannot be provably stale. */ public int length() { if(length == -1) { try { length = JDWP.ArrayReference.Length. process(vm, this).arrayLength; } catch (JDWPException exc) { throw exc.toJDIException(); } } return length; } public Value getValue(int index) { List<Value> list = getValues(index, 1); return list.get(0); } public List<Value> getValues() { return getValues(0, -1); } /** * Validate that the range to set/get is valid. * length of -1 (meaning rest of array) has been converted * before entry. */ private void validateArrayAccess(int index, int length) { // because length can be computed from index, // index must be tested first for correct error message if ((index < 0) || (index > length())) { throw new IndexOutOfBoundsException( "Invalid array index: " + index); } if (length < 0) { throw new IndexOutOfBoundsException( "Invalid array range length: " + length); } if (index + length > length()) { throw new IndexOutOfBoundsException( "Invalid array range: " + index + " to " + (index + length - 1)); } } @SuppressWarnings("unchecked") private static <T> T cast(Object x) { return (T)x; } public List<Value> getValues(int index, int length) { if (length == -1) { // -1 means the rest of the array length = length() - index; } validateArrayAccess(index, length); if (length == 0) { return new ArrayList<Value>(); } List<Value> vals; try { vals = cast(JDWP.ArrayReference.GetValues.process(vm, this, index, length).values); } catch (JDWPException exc) { throw exc.toJDIException(); } return vals; } public void setValue(int index, Value value) throws InvalidTypeException, ClassNotLoadedException { List<Value> list = new ArrayList<Value>(1); list.add(value); setValues(index, list, 0, 1); } public void setValues(List<? extends Value> values) throws InvalidTypeException, ClassNotLoadedException { setValues(0, values, 0, -1); } public void setValues(int index, List<? extends Value> values, int srcIndex, int length) throws InvalidTypeException, ClassNotLoadedException { if (length == -1) { // -1 means the rest of the array // shorter of, the rest of the array and rest of // the source values length = Math.min(length() - index, values.size() - srcIndex); } validateMirrorsOrNulls(values); validateArrayAccess(index, length); if ((srcIndex < 0) || (srcIndex > values.size())) { throw new IndexOutOfBoundsException( "Invalid source index: " + srcIndex); } if (srcIndex + length > values.size()) { throw new IndexOutOfBoundsException( "Invalid source range: " + srcIndex + " to " + (srcIndex + length - 1)); } boolean somethingToSet = false;; ValueImpl[] setValues = new ValueImpl[length]; for (int i = 0; i < length; i++) { ValueImpl value = (ValueImpl)values.get(srcIndex + i); try { // Validate and convert if necessary setValues[i] = ValueImpl.prepareForAssignment(value, new Component()); somethingToSet = true; } catch (ClassNotLoadedException e) { /* * Since we got this exception, * the component must be a reference type. * This means the class has not yet been loaded * through the defining class's class loader. * If the value we're trying to set is null, * then setting to null is essentially a * no-op, and we should allow it without an * exception. */ if (value != null) { throw e; } } } if (somethingToSet) { try { JDWP.ArrayReference.SetValues. process(vm, this, index, setValues); } catch (JDWPException exc) { throw exc.toJDIException(); } } } public String toString() { return "instance of " + arrayType().componentTypeName() + "[" + length() + "] (id=" + uniqueID() + ")"; } byte typeValueKey() { return JDWP.Tag.ARRAY; } void validateAssignment(ValueContainer destination) throws InvalidTypeException, ClassNotLoadedException { try { super.validateAssignment(destination); } catch (ClassNotLoadedException e) { /* * An array can be used extensively without the * enclosing loader being recorded by the VM as an * initiating loader of the array type. In addition, the * load of an array class is fairly harmless as long as * the component class is already loaded. So we relax the * rules a bit and allow the assignment as long as the * ultimate component types are assignable. */ boolean valid = false; JNITypeParser destParser = new JNITypeParser( destination.signature()); JNITypeParser srcParser = new JNITypeParser( arrayType().signature()); int destDims = destParser.dimensionCount(); if (destDims <= srcParser.dimensionCount()) { /* * Remove all dimensions from the destination. Remove * the same number of dimensions from the source. * Get types for both and check to see if they are * compatible. */ String destComponentSignature = destParser.componentSignature(destDims); Type destComponentType = destination.findType(destComponentSignature); String srcComponentSignature = srcParser.componentSignature(destDims); Type srcComponentType = arrayType().findComponentType(srcComponentSignature); valid = ArrayTypeImpl.isComponentAssignable(destComponentType, srcComponentType); } if (!valid) { throw new InvalidTypeException("Cannot assign " + arrayType().name() + " to " + destination.typeName()); } } } /* * Represents an array component to other internal parts of this * implementation. This is not exposed at the JDI level. Currently, * this class is needed only for type checking so it does not even * reference a particular component - just a generic component * of this array. In the future we may need to expand its use. */ class Component implements ValueContainer { public Type type() throws ClassNotLoadedException { return arrayType().componentType(); } public String typeName() { return arrayType().componentTypeName(); } public String signature() { return arrayType().componentSignature(); } public Type findType(String signature) throws ClassNotLoadedException { return arrayType().findComponentType(signature); } } }
Changed text
Open file
/* * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * * Copyright (C) 2019 JetBrains s.r.o. * * This program is free software; you can redistribute and/or modify it under * the terms of the GNU General Public License v2 with Classpath Exception. * The text of the license is available in the file LICENSE.TXT. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.TXT for more details. * * You may contact JetBrains s.r.o. at Na Hřebenech II 1718/10, 140 00 Prague, * Czech Republic or at legal@jetbrains.com. */ package com.jetbrains.jdi; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import com.sun.jdi.ArrayReference; import com.sun.jdi.ClassNotLoadedException; import com.sun.jdi.InvalidTypeException; import com.sun.jdi.Method; import com.sun.jdi.Type; import com.sun.jdi.Value; import com.sun.jdi.VirtualMachine; public class ArrayReferenceImpl extends ObjectReferenceImpl implements ArrayReference { private volatile int length = -1; ArrayReferenceImpl(VirtualMachine aVm, long aRef) { super(aVm, aRef); } protected ClassTypeImpl invokableReferenceType(Method method) { // The method has to be a method on Object since // arrays don't have methods nor any other 'superclasses' // So, use the ClassTypeImpl for Object instead of // the ArrayTypeImpl for the array itself. return (ClassTypeImpl)method.declaringType(); } ArrayTypeImpl arrayType() { return (ArrayTypeImpl)type(); } /** * Return array length. * Need not be synchronized since it cannot be provably stale. */ public int length() { if(length == -1) { try { length = JDWP.ArrayReference.Length. process(vm, this).arrayLength; } catch (JDWPException exc) { throw exc.toJDIException(); } } return length; } public CompletableFuture<Integer> lengthAsync() { if (length != -1) { return CompletableFuture.completedFuture(length); } return JDWP.ArrayReference.Length.processAsync(vm, this).thenApply(r -> length = r.arrayLength); } void setLength(int length) { this.length = length; } public Value getValue(int index) { return getValues(index, 1).get(0); } public CompletableFuture<Value> getValueAsync(int index) { return getValuesAsync(index, 1).thenApply(r -> r.get(0)); } public List<Value> getValues() { return getValues(0, -1); } public CompletableFuture<List<Value>> getValuesAsync() { return getValuesAsync(0, -1); } /** * Validate that the range to set/get is valid. * length of -1 (meaning rest of array) has been converted * before entry. */ private void validateArrayAccess(int index, int length) { // because length can be computed from index, // index must be tested first for correct error message if ((index < 0) || (index > length())) { throw new IndexOutOfBoundsException( "Invalid array index: " + index); } if (length < 0) { throw new IndexOutOfBoundsException( "Invalid array range length: " + length); } if (index + length > length()) { throw new IndexOutOfBoundsException( "Invalid array range: " + index + " to " + (index + length - 1)); } } @SuppressWarnings("unchecked") private static <T> T cast(Object x) { return (T)x; } public CompletableFuture<List<Value>> getValuesAsync(int index, int len) { return lengthAsync().thenCompose(__ -> { // preload length int length = len; if (length == -1) { // -1 means the rest of the array length = length() - index; } validateArrayAccess(index, length); if (length == 0) { return CompletableFuture.completedFuture(Collections.emptyList()); } return JDWP.ArrayReference.GetValues.processAsync(vm, this, index, length) .thenApply(r -> cast(r.values)); }); } public List<Value> getValues(int index, int length) { if (length == -1) { // -1 means the rest of the array length = length() - index; } validateArrayAccess(index, length); if (length == 0) { return Collections.emptyList(); } List<Value> vals; try { vals = cast(JDWP.ArrayReference.GetValues.process(vm, this, index, length).values); } catch (JDWPException exc) { throw exc.toJDIException(); } return vals; } public void setValue(int index, Value value) throws InvalidTypeException, ClassNotLoadedException { setValues(index, Collections.singletonList(value), 0, 1); } public void setValues(List<? extends Value> values) throws InvalidTypeException, ClassNotLoadedException { setValues(0, values, 0, -1); } public void setValues(int index, List<? extends Value> values, int srcIndex, int length) throws InvalidTypeException, ClassNotLoadedException { setValues(index, values, srcIndex, length, true); } public void setValues(int index, List<? extends Value> values, int srcIndex, int length, boolean checkAssignable) throws InvalidTypeException, ClassNotLoadedException { if (length == -1) { // -1 means the rest of the array // shorter of, the rest of the array and rest of // the source values length = Math.min(length() - index, values.size() - srcIndex); } validateMirrorsOrNulls(values); validateArrayAccess(index, length); if ((srcIndex < 0) || (srcIndex > values.size())) { throw new IndexOutOfBoundsException( "Invalid source index: " + srcIndex); } if (srcIndex + length > values.size()) { throw new IndexOutOfBoundsException( "Invalid source range: " + srcIndex + " to " + (srcIndex + length - 1)); } boolean somethingToSet = false; ValueImpl[] setValues = new ValueImpl[length]; for (int i = 0; i < length; i++) { ValueImpl value = (ValueImpl)values.get(srcIndex + i); try { // Validate and convert if necessary setValues[i] = prepareForAssignment(value, new Component(checkAssignable)); somethingToSet = true; } catch (ClassNotLoadedException e) { /* * Since we got this exception, * the component must be a reference type. * This means the class has not yet been loaded * through the defining class's class loader. * If the value we're trying to set is null, * then setting to null is essentially a * no-op, and we should allow it without an * exception. */ if (value != null) { throw e; } } } if (somethingToSet) { try { JDWP.ArrayReference.SetValues. process(vm, this, index, setValues); } catch (JDWPException exc) { throw exc.toJDIException(); } } } public String toString() { return "instance of " + arrayType().componentTypeName() + "[" + length() + "] (id=" + uniqueID() + ")"; } byte typeValueKey() { return JDWP.Tag.ARRAY; } void validateAssignment(ValueContainer destination) throws InvalidTypeException, ClassNotLoadedException { try { super.validateAssignment(destination); } catch (ClassNotLoadedException e) { /* * An array can be used extensively without the * enclosing loader being recorded by the VM as an * initiating loader of the array type. In addition, the * load of an array class is fairly harmless as long as * the component class is already loaded. So we relax the * rules a bit and allow the assignment as long as the * ultimate component types are assignable. */ boolean valid = false; JNITypeParser destParser = new JNITypeParser( destination.signature()); JNITypeParser srcParser = new JNITypeParser( arrayType().signature()); int destDims = destParser.dimensionCount(); if (destDims <= srcParser.dimensionCount()) { /* * Remove all dimensions from the destination. Remove * the same number of dimensions from the source. * Get types for both and check to see if they are * compatible. */ String destComponentSignature = destParser.componentSignature(destDims); Type destComponentType = destination.findType(destComponentSignature); String srcComponentSignature = srcParser.componentSignature(destDims); Type srcComponentType = arrayType().findComponentType(srcComponentSignature); valid = ArrayTypeImpl.isComponentAssignable(destComponentType, srcComponentType); } if (!valid) { throw new InvalidTypeException("Cannot assign " + arrayType().name() + " to " + destination.typeName()); } } } /* * Represents an array component to other internal parts of this * implementation. This is not exposed at the JDI level. Currently, * this class is needed only for type checking so it does not even * reference a particular component - just a generic component * of this array. In the future we may need to expand its use. */ class Component implements ValueContainer { private final boolean checkAssignable; public Component(boolean checkAssignable) { super(); this.checkAssignable = checkAssignable; } public Type type() throws ClassNotLoadedException { return arrayType().componentType(); } public String typeName() { return arrayType().componentTypeName(); } public String signature() { return arrayType().componentSignature(); } public Type findType(String signature) throws ClassNotLoadedException { return arrayType().findComponentType(signature); } @Override public boolean checkAssignable() { return checkAssignable; } } }
Find difference