Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
ArrayReferenceImpl
Creato
6 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
Spiegare
20 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
284 linee
Copia tutti
87 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
351 linee
Copia tutti
/*
/*
Copia
Copiato
Copia
Copiato
* 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.
Copia
Copiato
Copia
Copiato
*
* 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.
*/
*/
Copia
Copiato
Copia
Copiato
package com.
sun.tools
.jdi;
package com.
jetbrains
.jdi;
import com.sun.jdi.*;
Copia
Copiato
Copia
Copiato
import java.util.Collections;
import java.util.List;
import java.util.List;
Copia
Copiato
Copia
Copiato
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
{
{
Copia
Copiato
Copia
Copiato
int length = -1;
private volatile
int length = -1;
Copia
Copiato
Copia
Copiato
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;
}
}
Copia
Copiato
Copia
Copiato
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) {
Copia
Copiato
Copia
Copiato
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);
}
}
Copia
Copiato
Copia
Copiato
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;
}
}
Copia
Copiato
Copia
Copiato
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) {
Copia
Copiato
Copia
Copiato
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 {
Copia
Copiato
Copia
Copiato
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,
Copia
Copiato
Copia
Copiato
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));
}
}
Copia
Copiato
Copia
Copiato
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
Copia
Copiato
Copia
Copiato
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 {
Copia
Copiato
Copia
Copiato
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);
}
}
Copia
Copiato
Copia
Copiato
@Override
public boolean checkAssignable() {
return checkAssignable;
}
}
}
}
}
Diff salvati
Testo originale
Apri 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); } } }
Testo modificato
Apri 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; } } }
Trovare la differenza