feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,273 @@
/*
* Copyright (c) 1999, 2013, 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.tools.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import com.sun.jdi.*;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import java.io.InterruptedIOException;
abstract class AbstractLauncher extends ConnectorImpl implements LaunchingConnector {
abstract public VirtualMachine
launch(Map<String,? extends Connector.Argument> arguments)
throws IOException,
IllegalConnectorArgumentsException,
VMStartException;
abstract public String name();
abstract public String description();
ThreadGroup grp;
AbstractLauncher() {
super();
grp = Thread.currentThread().getThreadGroup();
ThreadGroup parent = null;
while ((parent = grp.getParent()) != null) {
grp = parent;
}
}
String[] tokenizeCommand(String command, char quote) {
String quoteStr = String.valueOf(quote); // easier to deal with
/*
* Tokenize the command, respecting the given quote character.
*/
StringTokenizer tokenizer = new StringTokenizer(command,
quote + " \t\r\n\f",
true);
String quoted = null;
String pending = null;
List<String> tokenList = new ArrayList<String>();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if (quoted != null) {
if (token.equals(quoteStr)) {
tokenList.add(quoted);
quoted = null;
} else {
quoted += token;
}
} else if (pending != null) {
if (token.equals(quoteStr)) {
quoted = pending;
} else if ((token.length() == 1) &&
Character.isWhitespace(token.charAt(0))) {
tokenList.add(pending);
} else {
throw new InternalException("Unexpected token: " + token);
}
pending = null;
} else {
if (token.equals(quoteStr)) {
quoted = "";
} else if ((token.length() == 1) &&
Character.isWhitespace(token.charAt(0))) {
// continue
} else {
pending = token;
}
}
}
/*
* Add final token.
*/
if (pending != null) {
tokenList.add(pending);
}
/*
* An unclosed quote at the end of the command. Do an
* implicit end quote.
*/
if (quoted != null) {
tokenList.add(quoted);
}
String[] tokenArray = new String[tokenList.size()];
for (int i = 0; i < tokenList.size(); i++) {
tokenArray[i] = tokenList.get(i);
}
return tokenArray;
}
protected VirtualMachine launch(String[] commandArray, String address,
TransportService.ListenKey listenKey,
TransportService ts)
throws IOException, VMStartException {
Helper helper = new Helper(commandArray, address, listenKey, ts);
helper.launchAndAccept();
VirtualMachineManager manager =
Bootstrap.virtualMachineManager();
return manager.createVirtualMachine(helper.connection(),
helper.process());
}
/**
* This class simply provides a context for a single launch and
* accept. It provides instance fields that can be used by
* all threads involved. This stuff can't be in the Connector proper
* because the connector is a singleton and is not specific to any
* one launch.
*/
private class Helper {
private final String address;
private TransportService.ListenKey listenKey;
private TransportService ts;
private final String[] commandArray;
private Process process = null;
private Connection connection = null;
private IOException acceptException = null;
private boolean exited = false;
Helper(String[] commandArray, String address, TransportService.ListenKey listenKey,
TransportService ts) {
this.commandArray = commandArray;
this.address = address;
this.listenKey = listenKey;
this.ts = ts;
}
String commandString() {
String str = "";
for (int i = 0; i < commandArray.length; i++) {
if (i > 0) {
str += " ";
}
str += commandArray[i];
}
return str;
}
synchronized void launchAndAccept() throws
IOException, VMStartException {
process = Runtime.getRuntime().exec(commandArray);
Thread acceptingThread = acceptConnection();
Thread monitoringThread = monitorTarget();
try {
while ((connection == null) &&
(acceptException == null) &&
!exited) {
wait();
}
if (exited) {
throw new VMStartException(
"VM initialization failed for: " + commandString(), process);
}
if (acceptException != null) {
// Rethrow the exception in this thread
throw acceptException;
}
} catch (InterruptedException e) {
throw new InterruptedIOException("Interrupted during accept");
} finally {
acceptingThread.interrupt();
monitoringThread.interrupt();
}
}
Process process() {
return process;
}
Connection connection() {
return connection;
}
synchronized void notifyOfExit() {
exited = true;
notify();
}
synchronized void notifyOfConnection(Connection connection) {
this.connection = connection;
notify();
}
synchronized void notifyOfAcceptException(IOException acceptException) {
this.acceptException = acceptException;
notify();
}
Thread monitorTarget() {
Thread thread = new Thread(grp,
"launched target monitor") {
public void run() {
try {
process.waitFor();
/*
* Notify waiting thread of VM error termination
*/
notifyOfExit();
} catch (InterruptedException e) {
// Connection has been established, stop monitoring
}
}
};
thread.setDaemon(true);
thread.start();
return thread;
}
Thread acceptConnection() {
Thread thread = new Thread(grp,
"connection acceptor") {
public void run() {
try {
Connection connection = ts.accept(listenKey, 0, 0);
/*
* Notify waiting thread of connection
*/
notifyOfConnection(connection);
} catch (InterruptedIOException e) {
// VM terminated, stop accepting
} catch (IOException e) {
// Report any other exception to waiting thread
notifyOfAcceptException(e);
}
}
};
thread.setDaemon(true);
thread.start();
return thread;
}
}
}

View File

@@ -0,0 +1,283 @@
/*
* 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);
}
}
}

View File

@@ -0,0 +1,208 @@
/*
* 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.Iterator;
import java.util.Map;
import java.util.Set;
public class ArrayTypeImpl extends ReferenceTypeImpl
implements ArrayType
{
protected ArrayTypeImpl(VirtualMachine aVm, long aRef) {
super(aVm, aRef);
}
public ArrayReference newInstance(int length) {
try {
return (ArrayReference)JDWP.ArrayType.NewInstance.
process(vm, this, length).newArray;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
public String componentSignature() {
return signature().substring(1); // Just skip the leading '['
}
public String componentTypeName() {
JNITypeParser parser = new JNITypeParser(componentSignature());
return parser.typeName();
}
Type type() throws ClassNotLoadedException {
return findType(componentSignature());
}
@Override
void addVisibleMethods(Map<String, Method> map, Set<InterfaceType> seenInterfaces) {
// arrays don't have methods
}
public List<Method> allMethods() {
return new ArrayList<Method>(0); // arrays don't have methods
}
/*
* Find the type object, if any, of a component type of this array.
* The component type does not have to be immediate; e.g. this method
* can be used to find the component Foo of Foo[][]. This method takes
* advantage of the property that an array and its component must have
* the same class loader. Since array set operations don't have an
* implicit enclosing type like field and variable set operations,
* this method is sometimes needed for proper type checking.
*/
Type findComponentType(String signature) throws ClassNotLoadedException {
byte tag = (byte)signature.charAt(0);
if (PacketStream.isObjectTag(tag)) {
// It's a reference type
JNITypeParser parser = new JNITypeParser(componentSignature());
List<ReferenceType> list = vm.classesByName(parser.typeName());
Iterator<ReferenceType> iter = list.iterator();
while (iter.hasNext()) {
ReferenceType type = iter.next();
ClassLoaderReference cl = type.classLoader();
if ((cl == null)?
(classLoader() == null) :
(cl.equals(classLoader()))) {
return type;
}
}
// Component class has not yet been loaded
throw new ClassNotLoadedException(componentTypeName());
} else {
// It's a primitive type
return vm.primitiveTypeMirror(tag);
}
}
public Type componentType() throws ClassNotLoadedException {
return findComponentType(componentSignature());
}
static boolean isComponentAssignable(Type destination, Type source) {
if (source instanceof PrimitiveType) {
// Assignment of primitive arrays requires identical
// component types.
return source.equals(destination);
} else {
if (destination instanceof PrimitiveType) {
return false;
}
ReferenceTypeImpl refSource = (ReferenceTypeImpl)source;
ReferenceTypeImpl refDestination = (ReferenceTypeImpl)destination;
// Assignment of object arrays requires availability
// of widening conversion of component types
return refSource.isAssignableTo(refDestination);
}
}
/*
* Return true if an instance of the given reference type
* can be assigned to a variable of this type
*/
boolean isAssignableTo(ReferenceType destType) {
if (destType instanceof ArrayType) {
try {
Type destComponentType = ((ArrayType)destType).componentType();
return isComponentAssignable(destComponentType, componentType());
} catch (ClassNotLoadedException e) {
// One or both component types has not yet been
// loaded => can't assign
return false;
}
} else if (destType instanceof InterfaceType) {
// Only valid InterfaceType assignee is Cloneable
return destType.name().equals("java.lang.Cloneable");
} else {
// Only valid ClassType assignee is Object
return destType.name().equals("java.lang.Object");
}
}
List<ReferenceType> inheritedTypes() {
return new ArrayList<ReferenceType>(0);
}
void getModifiers() {
if (modifiers != -1) {
return;
}
/*
* For object arrays, the return values for Interface
* Accessible.isPrivate(), Accessible.isProtected(),
* etc... are the same as would be returned for the
* component type. Fetch the modifier bits from the
* component type and use those.
*
* For primitive arrays, the modifiers are always
* VMModifiers.FINAL | VMModifiers.PUBLIC
*
* Reference com.sun.jdi.Accessible.java.
*/
try {
Type t = componentType();
if (t instanceof PrimitiveType) {
modifiers = VMModifiers.FINAL | VMModifiers.PUBLIC;
} else {
ReferenceType rt = (ReferenceType)t;
modifiers = rt.modifiers();
}
} catch (ClassNotLoadedException cnle) {
cnle.printStackTrace();
}
}
public String toString() {
return "array class " + name() + " (" + loaderString() + ")";
}
/*
* Save a pointless trip over the wire for these methods
* which have undefined results for arrays.
*/
public boolean isPrepared() { return true; }
public boolean isVerified() { return true; }
public boolean isInitialized() { return true; }
public boolean failedToInitialize() { return false; }
public boolean isAbstract() { return false; }
/*
* Defined always to be true for arrays
*/
public boolean isFinal() { return true; }
/*
* Defined always to be false for arrays
*/
public boolean isStatic() { return false; }
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 2001, 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.*;
class BaseLineInfo implements LineInfo {
private final int lineNumber;
private final ReferenceTypeImpl declaringType;
BaseLineInfo(int lineNumber,
ReferenceTypeImpl declaringType) {
this.lineNumber = lineNumber;
this.declaringType = declaringType;
}
public String liStratum() {
return SDE.BASE_STRATUM_NAME;
}
public int liLineNumber() {
return lineNumber;
}
public String liSourceName()
throws AbsentInformationException {
return declaringType.baseSourceName();
}
public String liSourcePath()
throws AbsentInformationException {
return declaringType.baseSourcePath();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class BooleanTypeImpl extends PrimitiveTypeImpl implements BooleanType {
BooleanTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.BOOLEAN);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedBooleanValue());
}
}

View File

@@ -0,0 +1,103 @@
/*
* 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.*;
public class BooleanValueImpl extends PrimitiveValueImpl
implements BooleanValue {
private boolean value;
BooleanValueImpl(VirtualMachine aVm,boolean aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof BooleanValue)) {
return (value == ((BooleanValue)obj).value())
&& super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public Type type() {
return vm.theBooleanType();
}
public boolean value() {
return value;
}
public boolean booleanValue() {
return value;
}
public byte byteValue() {
return(byte)((value)?1:0);
}
public char charValue() {
return(char)((value)?1:0);
}
public short shortValue() {
return(short)((value)?1:0);
}
public int intValue() {
return (value)?1:0;
}
public long longValue() {
return(long)((value)?1:0);
}
public float floatValue() {
return(float)((value)?1.0:0.0);
}
public double doubleValue() {
return (value)?1.0:0.0;
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.BOOLEAN;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class ByteTypeImpl extends PrimitiveTypeImpl implements ByteType {
ByteTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.BYTE);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedByteValue());
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1998, 2004, 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.*;
public class ByteValueImpl extends PrimitiveValueImpl
implements ByteValue {
private byte value;
ByteValueImpl(VirtualMachine aVm,byte aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof ByteValue)) {
return (value == ((ByteValue)obj).value())
&& super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public int compareTo(ByteValue obj) {
byte other = obj.value();
return value() - other;
}
public Type type() {
return vm.theByteType();
}
public byte value() {
return value;
}
public boolean booleanValue() {
return(value == 0)?false:true;
}
public byte byteValue() {
return value;
}
public char charValue() {
return(char)value;
}
public short shortValue() {
return(short)value;
}
public int intValue() {
return(int)value;
}
public long longValue() {
return(long)value;
}
public float floatValue() {
return(float)value;
}
public double doubleValue() {
return(double)value;
}
char checkedCharValue() throws InvalidTypeException {
if ((value > Character.MAX_VALUE) || (value < Character.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to char");
} else {
return super.checkedCharValue();
}
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.BYTE;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class CharTypeImpl extends PrimitiveTypeImpl implements CharType {
CharTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.CHAR);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedCharValue());
}
}

View File

@@ -0,0 +1,126 @@
/*
* 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.*;
public class CharValueImpl extends PrimitiveValueImpl
implements CharValue {
private char value;
CharValueImpl(VirtualMachine aVm,char aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof CharValue)) {
return (value == ((CharValue)obj).value()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public int compareTo(CharValue obj) {
char other = obj.value();
return value() - other;
}
public Type type() {
return vm.theCharType();
}
public char value() {
return value;
}
public boolean booleanValue() {
return(value == 0)?false:true;
}
public byte byteValue() {
return(byte)value;
}
public char charValue() {
return value;
}
public short shortValue() {
return(short)value;
}
public int intValue() {
return(int)value;
}
public long longValue() {
return(long)value;
}
public float floatValue() {
return(float)value;
}
public double doubleValue() {
return(double)value;
}
public String toString() {
return "" + value;
}
byte checkedByteValue() throws InvalidTypeException {
// Note: since char is unsigned, don't check against MIN_VALUE
if (value > Byte.MAX_VALUE) {
throw new InvalidTypeException("Can't convert " + value + " to byte");
} else {
return super.checkedByteValue();
}
}
short checkedShortValue() throws InvalidTypeException {
// Note: since char is unsigned, don't check against MIN_VALUE
if (value > Short.MAX_VALUE) {
throw new InvalidTypeException("Can't convert " + value + " to short");
} else {
return super.checkedShortValue();
}
}
byte typeValueKey() {
return JDWP.Tag.CHAR;
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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.*;
public class ClassLoaderReferenceImpl extends ObjectReferenceImpl
implements ClassLoaderReference, VMListener {
// This is cached only while the VM is suspended
private static class Cache extends ObjectReferenceImpl.Cache {
List<ReferenceType> visibleClasses = null;
}
protected ObjectReferenceImpl.Cache newCache() {
return new Cache();
}
ClassLoaderReferenceImpl(VirtualMachine aVm, long ref) {
super(aVm, ref);
vm.state().addListener(this);
}
protected String description() {
return "ClassLoaderReference " + uniqueID();
}
public List<ReferenceType> definedClasses() {
ArrayList<ReferenceType> definedClasses = new ArrayList<ReferenceType>();
for (ReferenceType type : vm.allClasses()) {
if (type.isPrepared() &&
equals(type.classLoader())) {
definedClasses.add(type);
}
}
return definedClasses;
}
public List<ReferenceType> visibleClasses() {
List<ReferenceType> classes = null;
try {
Cache local = (Cache)getCache();
if (local != null) {
classes = local.visibleClasses;
}
if (classes == null) {
JDWP.ClassLoaderReference.VisibleClasses.ClassInfo[]
jdwpClasses = JDWP.ClassLoaderReference.VisibleClasses.
process(vm, this).classes;
classes = new ArrayList<ReferenceType>(jdwpClasses.length);
for (int i = 0; i < jdwpClasses.length; ++i) {
classes.add(vm.referenceType(jdwpClasses[i].typeID,
jdwpClasses[i].refTypeTag));
}
classes = Collections.unmodifiableList(classes);
if (local != null) {
local.visibleClasses = classes;
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching visible classes (count = " +
classes.size() + ")");
}
}
}
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return classes;
}
Type findType(String signature) throws ClassNotLoadedException {
List<ReferenceType> types = visibleClasses();
Iterator<ReferenceType> iter = types.iterator();
while (iter.hasNext()) {
ReferenceType type = iter.next();
if (type.signature().equals(signature)) {
return type;
}
}
JNITypeParser parser = new JNITypeParser(signature);
throw new ClassNotLoadedException(parser.typeName(),
"Class " + parser.typeName() + " not loaded");
}
byte typeValueKey() {
return JDWP.Tag.CLASS_LOADER;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1999, 2000, 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.*;
public class ClassObjectReferenceImpl extends ObjectReferenceImpl
implements ClassObjectReference {
private ReferenceType reflectedType;
ClassObjectReferenceImpl(VirtualMachine vm, long ref) {
super(vm, ref);
}
public ReferenceType reflectedType() {
if (reflectedType == null) {
try {
JDWP.ClassObjectReference.ReflectedType reply =
JDWP.ClassObjectReference.ReflectedType.process(vm, this);
reflectedType = vm.referenceType(reply.typeID,
reply.refTypeTag);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
return reflectedType;
}
byte typeValueKey() {
return JDWP.Tag.CLASS_OBJECT;
}
public String toString() {
return "instance of " + referenceType().name() +
"(reflected class=" + reflectedType().name() + ", " + "id=" + uniqueID() + ")";
}
}

View File

@@ -0,0 +1,296 @@
/*
* 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.*;
final public class ClassTypeImpl extends InvokableTypeImpl
implements ClassType
{
private static class IResult implements InvocationResult {
final private JDWP.ClassType.InvokeMethod rslt;
public IResult(JDWP.ClassType.InvokeMethod rslt) {
this.rslt = rslt;
}
@Override
public ObjectReferenceImpl getException() {
return rslt.exception;
}
@Override
public ValueImpl getResult() {
return rslt.returnValue;
}
}
private boolean cachedSuperclass = false;
private ClassType superclass = null;
private int lastLine = -1;
private List<InterfaceType> interfaces = null;
protected ClassTypeImpl(VirtualMachine aVm,long aRef) {
super(aVm, aRef);
}
public ClassType superclass() {
if(!cachedSuperclass) {
ClassTypeImpl sup = null;
try {
sup = JDWP.ClassType.Superclass.
process(vm, this).superclass;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
/*
* If there is a superclass, cache its
* ClassType here. Otherwise,
* leave the cache reference null.
*/
if (sup != null) {
superclass = sup;
}
cachedSuperclass = true;
}
return superclass;
}
@Override
public List<InterfaceType> interfaces() {
if (interfaces == null) {
interfaces = getInterfaces();
}
return interfaces;
}
@Override
public List<InterfaceType> allInterfaces() {
return getAllInterfaces();
}
public List<ClassType> subclasses() {
List<ClassType> subs = new ArrayList<ClassType>();
for (ReferenceType refType : vm.allClasses()) {
if (refType instanceof ClassType) {
ClassType clazz = (ClassType)refType;
ClassType superclass = clazz.superclass();
if ((superclass != null) && superclass.equals(this)) {
subs.add((ClassType)refType);
}
}
}
return subs;
}
public boolean isEnum() {
ClassType superclass = superclass();
if (superclass != null &&
superclass.name().equals("java.lang.Enum")) {
return true;
}
return false;
}
public void setValue(Field field, Value value)
throws InvalidTypeException, ClassNotLoadedException {
validateMirror(field);
validateMirrorOrNull(value);
validateFieldSet(field);
// More validation specific to setting from a ClassType
if(!field.isStatic()) {
throw new IllegalArgumentException(
"Must set non-static field through an instance");
}
try {
JDWP.ClassType.SetValues.FieldValue[] values =
new JDWP.ClassType.SetValues.FieldValue[1];
values[0] = new JDWP.ClassType.SetValues.FieldValue(
((FieldImpl)field).ref(),
// validate and convert if necessary
ValueImpl.prepareForAssignment(value, (FieldImpl)field));
try {
JDWP.ClassType.SetValues.process(vm, this, values);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
} catch (ClassNotLoadedException e) {
/*
* Since we got this exception,
* the field type must be a reference type. The value
* we're trying to set is null, but if the field's
* class has not yet been loaded through the enclosing
* class loader, then setting to null is essentially a
* no-op, and we should allow it without an exception.
*/
if (value != null) {
throw e;
}
}
}
PacketStream sendNewInstanceCommand(final ThreadReferenceImpl thread,
final MethodImpl method,
final ValueImpl[] args,
final int options) {
CommandSender sender =
new CommandSender() {
public PacketStream send() {
return JDWP.ClassType.NewInstance.enqueueCommand(
vm, ClassTypeImpl.this, thread,
method.ref(), args, options);
}
};
PacketStream stream;
if ((options & INVOKE_SINGLE_THREADED) != 0) {
stream = thread.sendResumingCommand(sender);
} else {
stream = vm.sendResumingCommand(sender);
}
return stream;
}
public ObjectReference newInstance(ThreadReference threadIntf,
Method methodIntf,
List<? extends Value> origArguments,
int options)
throws InvalidTypeException,
ClassNotLoadedException,
IncompatibleThreadStateException,
InvocationException {
validateMirror(threadIntf);
validateMirror(methodIntf);
validateMirrorsOrNulls(origArguments);
MethodImpl method = (MethodImpl)methodIntf;
ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf;
validateConstructorInvocation(method);
List<Value> arguments = method.validateAndPrepareArgumentsForInvoke(
origArguments);
ValueImpl[] args = arguments.toArray(new ValueImpl[0]);
JDWP.ClassType.NewInstance ret = null;
try {
PacketStream stream =
sendNewInstanceCommand(thread, method, args, options);
ret = JDWP.ClassType.NewInstance.waitForReply(vm, stream);
} catch (JDWPException exc) {
if (exc.errorCode() == JDWP.Error.INVALID_THREAD) {
throw new IncompatibleThreadStateException();
} else {
throw exc.toJDIException();
}
}
/*
* There is an implict VM-wide suspend at the conclusion
* of a normal (non-single-threaded) method invoke
*/
if ((options & INVOKE_SINGLE_THREADED) == 0) {
vm.notifySuspend();
}
if (ret.exception != null) {
throw new InvocationException(ret.exception);
} else {
return ret.newObject;
}
}
public Method concreteMethodByName(String name, String signature) {
Method method = null;
for (Method candidate : visibleMethods()) {
if (candidate.name().equals(name) &&
candidate.signature().equals(signature) &&
!candidate.isAbstract()) {
method = candidate;
break;
}
}
return method;
}
void validateConstructorInvocation(Method method)
throws InvalidTypeException,
InvocationException {
/*
* Method must be in this class.
*/
ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType();
if (!declType.equals(this)) {
throw new IllegalArgumentException("Invalid constructor");
}
/*
* Method must be a constructor
*/
if (!method.isConstructor()) {
throw new IllegalArgumentException("Cannot create instance with non-constructor");
}
}
public String toString() {
return "class " + name() + " (" + loaderString() + ")";
}
@Override
CommandSender getInvokeMethodSender(ThreadReferenceImpl thread,
MethodImpl method,
ValueImpl[] args,
int options) {
return () ->
JDWP.ClassType.InvokeMethod.enqueueCommand(vm,
ClassTypeImpl.this,
thread,
method.ref(),
args,
options);
}
@Override
InvocationResult waitForReply(PacketStream stream) throws JDWPException {
return new IResult(JDWP.ClassType.InvokeMethod.waitForReply(vm, stream));
}
@Override
boolean canInvoke(Method method) {
// Method must be in this class or a superclass.
return ((ReferenceTypeImpl)method.declaringType()).isAssignableFrom(this);
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (c) 1999, 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.EventListener;
interface CommandSender {
PacketStream send();
}

View File

@@ -0,0 +1,545 @@
/*
* Copyright (c) 2000, 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.Map;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.lang.ref.SoftReference;
/**
* Represents methods with method bodies.
* That is, non-native non-abstract methods.
* Private to MethodImpl.
*/
public class ConcreteMethodImpl extends MethodImpl {
/*
* A subset of the line number info that is softly cached
*/
static private class SoftLocationXRefs {
final String stratumID; // The stratum of this information
final Map<Integer, List<Location>> lineMapper; // Maps line number to location(s)
final List<Location> lineLocations; // List of locations ordered by code index
/*
* Note: these do not necessarily correspond to
* the line numbers of the first and last elements
* in the lineLocations list. Use these only for bounds
* checking and with lineMapper.
*/
final int lowestLine;
final int highestLine;
SoftLocationXRefs(String stratumID, Map<Integer, List<Location>> lineMapper, List<Location> lineLocations,
int lowestLine, int highestLine) {
this.stratumID = stratumID;
this.lineMapper = Collections.unmodifiableMap(lineMapper);
this.lineLocations =
Collections.unmodifiableList(lineLocations);
this.lowestLine = lowestLine;
this.highestLine = highestLine;
}
}
private Location location = null;
private SoftReference<SoftLocationXRefs> softBaseLocationXRefsRef;
private SoftReference<SoftLocationXRefs> softOtherLocationXRefsRef;
private SoftReference<List<LocalVariable>> variablesRef = null;
private boolean absentVariableInformation = false;
private long firstIndex = -1;
private long lastIndex = -1;
private SoftReference<byte[]> bytecodesRef = null;
private int argSlotCount = -1;
ConcreteMethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
long ref,
String name, String signature,
String genericSignature, int modifiers) {
// The generic signature is set when this is created
super(vm, declaringType, ref, name, signature,
genericSignature, modifiers);
}
public Location location() {
if (location == null) {
getBaseLocations();
}
return location;
}
List<Location> sourceNameFilter(List<Location> list,
SDE.Stratum stratum,
String sourceName)
throws AbsentInformationException {
if (sourceName == null) {
return list;
} else {
/* needs sourceName filteration */
List<Location> locs = new ArrayList<Location>();
for (Location loc : list) {
if (((LocationImpl)loc).sourceName(stratum).equals(sourceName)) {
locs.add(loc);
}
}
return locs;
}
}
List<Location> allLineLocations(SDE.Stratum stratum,
String sourceName)
throws AbsentInformationException {
List<Location> lineLocations = getLocations(stratum).lineLocations;
if (lineLocations.size() == 0) {
throw new AbsentInformationException();
}
return Collections.unmodifiableList(
sourceNameFilter(lineLocations, stratum, sourceName));
}
List<Location> locationsOfLine(SDE.Stratum stratum,
String sourceName,
int lineNumber)
throws AbsentInformationException {
SoftLocationXRefs info = getLocations(stratum);
if (info.lineLocations.size() == 0) {
throw new AbsentInformationException();
}
/*
* Find the locations which match the line number
* passed in.
*/
List<Location> list = info.lineMapper.get(new Integer(lineNumber));
if (list == null) {
list = new ArrayList<Location>(0);
}
return Collections.unmodifiableList(
sourceNameFilter(list, stratum, sourceName));
}
public Location locationOfCodeIndex(long codeIndex) {
if (firstIndex == -1) {
getBaseLocations();
}
/*
* Check for invalid code index.
*/
if (codeIndex < firstIndex || codeIndex > lastIndex) {
return null;
}
return new LocationImpl(virtualMachine(), this, codeIndex);
}
LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
long codeIndex) {
if (firstIndex == -1) {
getBaseLocations();
}
/*
* Check for invalid code index.
*/
if (codeIndex < firstIndex || codeIndex > lastIndex) {
throw new InternalError(
"Location with invalid code index");
}
List<Location> lineLocations = getLocations(stratum).lineLocations;
/*
* Check for absent line numbers.
*/
if (lineLocations.size() == 0) {
return super.codeIndexToLineInfo(stratum, codeIndex);
}
Iterator<Location> iter = lineLocations.iterator();
/*
* Treat code before the beginning of the first line table
* entry as part of the first line. javac will generate
* code like this for some local classes. This "prolog"
* code contains assignments from locals in the enclosing
* scope to synthetic fields in the local class. Same for
* other language prolog code.
*/
LocationImpl bestMatch = (LocationImpl)iter.next();
while (iter.hasNext()) {
LocationImpl current = (LocationImpl)iter.next();
if (current.codeIndex() > codeIndex) {
break;
}
bestMatch = current;
}
return bestMatch.getLineInfo(stratum);
}
public List<LocalVariable> variables() throws AbsentInformationException {
return getVariables();
}
public List<LocalVariable> variablesByName(String name) throws AbsentInformationException {
List<LocalVariable> variables = getVariables();
List<LocalVariable> retList = new ArrayList<LocalVariable>(2);
Iterator<LocalVariable> iter = variables.iterator();
while(iter.hasNext()) {
LocalVariable variable = iter.next();
if (variable.name().equals(name)) {
retList.add(variable);
}
}
return retList;
}
public List<LocalVariable> arguments() throws AbsentInformationException {
List<LocalVariable> variables = getVariables();
List<LocalVariable> retList = new ArrayList<LocalVariable>(variables.size());
Iterator<LocalVariable> iter = variables.iterator();
while(iter.hasNext()) {
LocalVariable variable = iter.next();
if (variable.isArgument()) {
retList.add(variable);
}
}
return retList;
}
public byte[] bytecodes() {
byte[] bytecodes = (bytecodesRef == null) ? null :
bytecodesRef.get();
if (bytecodes == null) {
try {
bytecodes = JDWP.Method.Bytecodes.
process(vm, declaringType, ref).bytes;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
bytecodesRef = new SoftReference<byte[]>(bytecodes);
}
/*
* Arrays are always modifiable, so it is a little unsafe
* to return the cached bytecodes directly; instead, we
* make a clone at the cost of using more memory.
*/
return bytecodes.clone();
}
int argSlotCount() throws AbsentInformationException {
if (argSlotCount == -1) {
getVariables();
}
return argSlotCount;
}
private SoftLocationXRefs getLocations(SDE.Stratum stratum) {
if (stratum.isJava()) {
return getBaseLocations();
}
String stratumID = stratum.id();
SoftLocationXRefs info =
(softOtherLocationXRefsRef == null) ? null :
softOtherLocationXRefsRef.get();
if (info != null && info.stratumID.equals(stratumID)) {
return info;
}
List<Location> lineLocations = new ArrayList<Location>();
Map<Integer, List<Location>> lineMapper = new HashMap<Integer, List<Location>>();
int lowestLine = -1;
int highestLine = -1;
SDE.LineStratum lastLineStratum = null;
SDE.Stratum baseStratum =
declaringType.stratum(SDE.BASE_STRATUM_NAME);
Iterator<Location> it = getBaseLocations().lineLocations.iterator();
while(it.hasNext()) {
LocationImpl loc = (LocationImpl)it.next();
int baseLineNumber = loc.lineNumber(baseStratum);
SDE.LineStratum lineStratum =
stratum.lineStratum(declaringType,
baseLineNumber);
if (lineStratum == null) {
// location not mapped in this stratum
continue;
}
int lineNumber = lineStratum.lineNumber();
// remove unmapped and dup lines
if ((lineNumber != -1) &&
(!lineStratum.equals(lastLineStratum))) {
lastLineStratum = lineStratum;
// Remember the largest/smallest line number
if (lineNumber > highestLine) {
highestLine = lineNumber;
}
if ((lineNumber < lowestLine) || (lowestLine == -1)) {
lowestLine = lineNumber;
}
loc.addStratumLineInfo(
new StratumLineInfo(stratumID,
lineNumber,
lineStratum.sourceName(),
lineStratum.sourcePath()));
// Add to the location list
lineLocations.add(loc);
// Add to the line -> locations map
Integer key = new Integer(lineNumber);
List<Location> mappedLocs = lineMapper.get(key);
if (mappedLocs == null) {
mappedLocs = new ArrayList<Location>(1);
lineMapper.put(key, mappedLocs);
}
mappedLocs.add(loc);
}
}
info = new SoftLocationXRefs(stratumID,
lineMapper, lineLocations,
lowestLine, highestLine);
softOtherLocationXRefsRef = new SoftReference<SoftLocationXRefs>(info);
return info;
}
private SoftLocationXRefs getBaseLocations() {
SoftLocationXRefs info = (softBaseLocationXRefsRef == null) ? null :
softBaseLocationXRefsRef.get();
if (info != null) {
return info;
}
JDWP.Method.LineTable lntab = null;
try {
lntab = JDWP.Method.LineTable.process(vm, declaringType, ref);
} catch (JDWPException exc) {
/*
* Note: the absent info error shouldn't happen here
* because the first and last index are always available.
*/
throw exc.toJDIException();
}
int count = lntab.lines.length;
List<Location> lineLocations = new ArrayList<Location>(count);
Map<Integer, List<Location>>lineMapper = new HashMap<Integer, List<Location>>();
int lowestLine = -1;
int highestLine = -1;
for (int i = 0; i < count; i++) {
long bci = lntab.lines[i].lineCodeIndex;
int lineNumber = lntab.lines[i].lineNumber;
/*
* Some compilers will point multiple consecutive
* lines at the same location. We need to choose
* one of them so that we can consistently map back
* and forth between line and location. So we choose
* to record only the last line entry at a particular
* location.
*/
if ((i + 1 == count) || (bci != lntab.lines[i+1].lineCodeIndex)) {
// Remember the largest/smallest line number
if (lineNumber > highestLine) {
highestLine = lineNumber;
}
if ((lineNumber < lowestLine) || (lowestLine == -1)) {
lowestLine = lineNumber;
}
LocationImpl loc =
new LocationImpl(virtualMachine(), this, bci);
loc.addBaseLineInfo(
new BaseLineInfo(lineNumber, declaringType));
// Add to the location list
lineLocations.add(loc);
// Add to the line -> locations map
Integer key = new Integer(lineNumber);
List<Location> mappedLocs = lineMapper.get(key);
if (mappedLocs == null) {
mappedLocs = new ArrayList<Location>(1);
lineMapper.put(key, mappedLocs);
}
mappedLocs.add(loc);
}
}
/*
* firstIndex, lastIndex, and startLocation need to be
* retrieved only once since they are strongly referenced.
*/
if (location == null) {
firstIndex = lntab.start;
lastIndex = lntab.end;
/*
* The startLocation is the first one in the
* location list if we have one;
* otherwise, we construct a location for a
* method start with no line info
*/
if (count > 0) {
location = lineLocations.get(0);
} else {
location = new LocationImpl(virtualMachine(), this,
firstIndex);
}
}
info = new SoftLocationXRefs(SDE.BASE_STRATUM_NAME,
lineMapper, lineLocations,
lowestLine, highestLine);
softBaseLocationXRefsRef = new SoftReference<SoftLocationXRefs>(info);
return info;
}
private List<LocalVariable> getVariables1_4() throws AbsentInformationException {
JDWP.Method.VariableTable vartab = null;
try {
vartab = JDWP.Method.VariableTable.
process(vm, declaringType, ref);
} catch (JDWPException exc) {
if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
absentVariableInformation = true;
throw new AbsentInformationException();
} else {
throw exc.toJDIException();
}
}
// Get the number of slots used by argument variables
argSlotCount = vartab.argCnt;
int count = vartab.slots.length;
List<LocalVariable> variables = new ArrayList<LocalVariable>(count);
for (int i=0; i<count; i++) {
JDWP.Method.VariableTable.SlotInfo si = vartab.slots[i];
/*
* Skip "this*" entries because they are never real
* variables from the JLS perspective.
*/
if (!si.name.startsWith("this$") && !si.name.equals("this")) {
Location scopeStart = new LocationImpl(virtualMachine(),
this, si.codeIndex);
Location scopeEnd =
new LocationImpl(virtualMachine(), this,
si.codeIndex + si.length - 1);
LocalVariable variable =
new LocalVariableImpl(virtualMachine(), this,
si.slot, scopeStart, scopeEnd,
si.name, si.signature, null);
// Add to the variable list
variables.add(variable);
}
}
return variables;
}
private List<LocalVariable> getVariables1() throws AbsentInformationException {
if (!vm.canGet1_5LanguageFeatures()) {
return getVariables1_4();
}
JDWP.Method.VariableTableWithGeneric vartab = null;
try {
vartab = JDWP.Method.VariableTableWithGeneric.
process(vm, declaringType, ref);
} catch (JDWPException exc) {
if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
absentVariableInformation = true;
throw new AbsentInformationException();
} else {
throw exc.toJDIException();
}
}
// Get the number of slots used by argument variables
argSlotCount = vartab.argCnt;
int count = vartab.slots.length;
List<LocalVariable> variables = new ArrayList<LocalVariable>(count);
for (int i=0; i<count; i++) {
JDWP.Method.VariableTableWithGeneric.SlotInfo si = vartab.slots[i];
/*
* Skip "this*" entries because they are never real
* variables from the JLS perspective.
*/
if (!si.name.startsWith("this$") && !si.name.equals("this")) {
Location scopeStart = new LocationImpl(virtualMachine(),
this, si.codeIndex);
Location scopeEnd =
new LocationImpl(virtualMachine(), this,
si.codeIndex + si.length - 1);
LocalVariable variable =
new LocalVariableImpl(virtualMachine(), this,
si.slot, scopeStart, scopeEnd,
si.name, si.signature,
si.genericSignature);
// Add to the variable list
variables.add(variable);
}
}
return variables;
}
private List<LocalVariable> getVariables() throws AbsentInformationException {
if (absentVariableInformation) {
throw new AbsentInformationException();
}
List<LocalVariable> variables = (variablesRef == null) ? null :
variablesRef.get();
if (variables != null) {
return variables;
}
variables = getVariables1();
variables = Collections.unmodifiableList(variables);
variablesRef = new SoftReference<List<LocalVariable>>(variables);
return variables;
}
}

View File

@@ -0,0 +1,425 @@
/*
* 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.tools.jdi.*;
import com.sun.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.InternalException;
import java.util.Collections;
import java.util.Collection;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.io.Serializable;
abstract class ConnectorImpl implements Connector {
Map<String,Argument> defaultArguments = new java.util.LinkedHashMap<String,Argument>();
// Used by BooleanArgument
static String trueString = null;
static String falseString;
public Map<String,Argument> defaultArguments() {
Map<String,Argument> defaults = new java.util.LinkedHashMap<String,Argument>();
Collection<Argument> values = defaultArguments.values();
Iterator<Argument> iter = values.iterator();
while (iter.hasNext()) {
ArgumentImpl argument = (ArgumentImpl)iter.next();
defaults.put(argument.name(), (Argument)argument.clone());
}
return defaults;
}
void addStringArgument(String name, String label, String description,
String defaultValue, boolean mustSpecify) {
defaultArguments.put(name,
new StringArgumentImpl(name, label,
description,
defaultValue,
mustSpecify));
}
void addBooleanArgument(String name, String label, String description,
boolean defaultValue, boolean mustSpecify) {
defaultArguments.put(name,
new BooleanArgumentImpl(name, label,
description,
defaultValue,
mustSpecify));
}
void addIntegerArgument(String name, String label, String description,
String defaultValue, boolean mustSpecify,
int min, int max) {
defaultArguments.put(name,
new IntegerArgumentImpl(name, label,
description,
defaultValue,
mustSpecify,
min, max));
}
void addSelectedArgument(String name, String label, String description,
String defaultValue, boolean mustSpecify,
List<String> list) {
defaultArguments.put(name,
new SelectedArgumentImpl(name, label,
description,
defaultValue,
mustSpecify, list));
}
ArgumentImpl argument(String name, Map<String, ? extends Argument> arguments)
throws IllegalConnectorArgumentsException {
ArgumentImpl argument = (ArgumentImpl)arguments.get(name);
if (argument == null) {
throw new IllegalConnectorArgumentsException(
"Argument missing", name);
}
String value = argument.value();
if (value == null || value.length() == 0) {
if (argument.mustSpecify()) {
throw new IllegalConnectorArgumentsException(
"Argument unspecified", name);
}
} else if(!argument.isValid(value)) {
throw new IllegalConnectorArgumentsException(
"Argument invalid", name);
}
return argument;
}
private ResourceBundle messages = null;
String getString(String key) {
if (messages == null) {
messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
}
return messages.getString(key);
}
public String toString() {
String string = name() + " (defaults: ";
Iterator<Argument> iter = defaultArguments().values().iterator();
boolean first = true;
while (iter.hasNext()) {
ArgumentImpl argument = (ArgumentImpl)iter.next();
if (!first) {
string += ", ";
}
string += argument.toString();
first = false;
}
string += ")";
return string;
}
abstract class ArgumentImpl implements Connector.Argument, Cloneable, Serializable {
private String name;
private String label;
private String description;
private String value;
private boolean mustSpecify;
ArgumentImpl(String name, String label, String description,
String value,
boolean mustSpecify) {
this.name = name;
this.label = label;
this.description = description;
this.value = value;
this.mustSpecify = mustSpecify;
}
public abstract boolean isValid(String value);
public String name() {
return name;
}
public String label() {
return label;
}
public String description() {
return description;
}
public String value() {
return value;
}
public void setValue(String value) {
if (value == null) {
throw new NullPointerException("Can't set null value");
}
this.value = value;
}
public boolean mustSpecify() {
return mustSpecify;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof Connector.Argument)) {
Connector.Argument other = (Connector.Argument)obj;
return (name().equals(other.name())) &&
(description().equals(other.description())) &&
(mustSpecify() == other.mustSpecify()) &&
(value().equals(other.value()));
} else {
return false;
}
}
public int hashCode() {
return description().hashCode();
}
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// Object should always support clone
throw new InternalException();
}
}
public String toString() {
return name() + "=" + value();
}
}
class BooleanArgumentImpl extends ConnectorImpl.ArgumentImpl
implements Connector.BooleanArgument {
private static final long serialVersionUID = 1624542968639361316L;
BooleanArgumentImpl(String name, String label, String description,
boolean value,
boolean mustSpecify) {
super(name, label, description, null, mustSpecify);
if(trueString == null) {
trueString = getString("true");
falseString = getString("false");
}
setValue(value);
}
/**
* Sets the value of the argument.
*/
public void setValue(boolean value) {
setValue(stringValueOf(value));
}
/**
* Performs basic sanity check of argument.
* @return <code>true</code> if value is a string
* representation of a boolean value.
* @see #stringValueOf(boolean)
*/
public boolean isValid(String value) {
return value.equals(trueString) || value.equals(falseString);
}
/**
* Return the string representation of the <code>value</code>
* parameter.
* Does not set or examine the value or the argument.
* @return the localized String representation of the
* boolean value.
*/
public String stringValueOf(boolean value) {
return value? trueString : falseString;
}
/**
* Return the value of the argument as a boolean. Since
* the argument may not have been set or may have an invalid
* value {@link #isValid(String)} should be called on
* {@link #value()} to check its validity. If it is invalid
* the boolean returned by this method is undefined.
* @return the value of the argument as a boolean.
*/
public boolean booleanValue() {
return value().equals(trueString);
}
}
class IntegerArgumentImpl extends ConnectorImpl.ArgumentImpl
implements Connector.IntegerArgument {
private static final long serialVersionUID = 763286081923797770L;
private final int min;
private final int max;
IntegerArgumentImpl(String name, String label, String description,
String value,
boolean mustSpecify, int min, int max) {
super(name, label, description, value, mustSpecify);
this.min = min;
this.max = max;
}
/**
* Sets the value of the argument.
* The value should be checked with {@link #isValid(int)}
* before setting it; invalid values will throw an exception
* when the connection is established - for example,
* on {@link LaunchingConnector#launch}
*/
public void setValue(int value) {
setValue(stringValueOf(value));
}
/**
* Performs basic sanity check of argument.
* @return <code>true</code> if value represents an int that is
* <code>{@link #min()} &lt;= value &lt;= {@link #max()}</code>
*/
public boolean isValid(String value) {
if (value == null) {
return false;
}
try {
return isValid(Integer.decode(value).intValue());
} catch(NumberFormatException exc) {
return false;
}
}
/**
* Performs basic sanity check of argument.
* @return <code>true</code> if
* <code>{@link #min()} &lt;= value &lt;= {@link #max()}</code>
*/
public boolean isValid(int value) {
return min <= value && value <= max;
}
/**
* Return the string representation of the <code>value</code>
* parameter.
* Does not set or examine the value or the argument.
* @return the String representation of the
* int value.
*/
public String stringValueOf(int value) {
// *** Should this be internationalized????
// *** Even Brian Beck was unsure if an Arabic programmer
// *** would expect port numbers in Arabic numerals,
// *** so punt for now.
return ""+value;
}
/**
* Return the value of the argument as a int. Since
* the argument may not have been set or may have an invalid
* value {@link #isValid(String)} should be called on
* {@link #value()} to check its validity. If it is invalid
* the int returned by this method is undefined.
* @return the value of the argument as a int.
*/
public int intValue() {
if (value() == null) {
return 0;
}
try {
return Integer.decode(value()).intValue();
} catch(NumberFormatException exc) {
return 0;
}
}
/**
* The upper bound for the value.
* @return the maximum allowed value for this argument.
*/
public int max() {
return max;
}
/**
* The lower bound for the value.
* @return the minimum allowed value for this argument.
*/
public int min() {
return min;
}
}
class StringArgumentImpl extends ConnectorImpl.ArgumentImpl
implements Connector.StringArgument {
private static final long serialVersionUID = 7500484902692107464L;
StringArgumentImpl(String name, String label, String description,
String value,
boolean mustSpecify) {
super(name, label, description, value, mustSpecify);
}
/**
* Performs basic sanity check of argument.
* @return <code>true</code> always
*/
public boolean isValid(String value) {
return true;
}
}
class SelectedArgumentImpl extends ConnectorImpl.ArgumentImpl
implements Connector.SelectedArgument {
private static final long serialVersionUID = -5689584530908382517L;
private final List<String> choices;
SelectedArgumentImpl(String name, String label, String description,
String value,
boolean mustSpecify, List<String> choices) {
super(name, label, description, value, mustSpecify);
this.choices = Collections.unmodifiableList(new ArrayList<String>(choices));
}
/**
* Return the possible values for the argument
* @return {@link List} of {@link String}
*/
public List<String> choices() {
return choices;
}
/**
* Performs basic sanity check of argument.
* @return <code>true</code> if value is one of {@link #choices()}.
*/
public boolean isValid(String value) {
return choices.contains(value);
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class DoubleTypeImpl extends PrimitiveTypeImpl implements DoubleType {
DoubleTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.DOUBLE);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedDoubleValue());
}
}

View File

@@ -0,0 +1,164 @@
/*
* 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.*;
public class DoubleValueImpl extends PrimitiveValueImpl
implements DoubleValue {
private double value;
DoubleValueImpl(VirtualMachine aVm,double aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof DoubleValue)) {
return (value == ((DoubleValue)obj).value()) &&
super.equals(obj);
} else {
return false;
}
}
public int compareTo(DoubleValue obj) {
double other = obj.value();
if (value() < other) {
return -1;
} else if (value() == other) {
return 0;
} else {
return 1;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public Type type() {
return vm.theDoubleType();
}
public double value() {
return value;
}
public boolean booleanValue() {
return(value == 0.0)?false:true;
}
public byte byteValue() {
return(byte)value;
}
public char charValue() {
return(char)value;
}
public short shortValue() {
return(short)value;
}
public int intValue() {
return(int)value;
}
public long longValue() {
return(long)value;
}
public float floatValue() {
return(float)value;
}
public double doubleValue() {
return value;
}
byte checkedByteValue() throws InvalidTypeException {
if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to byte");
} else {
return super.checkedByteValue();
}
}
char checkedCharValue() throws InvalidTypeException {
if ((value > Character.MAX_VALUE) || (value < Character.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to char");
} else {
return super.checkedCharValue();
}
}
short checkedShortValue() throws InvalidTypeException {
if ((value > Short.MAX_VALUE) || (value < Short.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to short");
} else {
return super.checkedShortValue();
}
}
int checkedIntValue() throws InvalidTypeException {
if ((value > Integer.MAX_VALUE) || (value < Integer.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to int");
} else {
return super.checkedIntValue();
}
}
long checkedLongValue() throws InvalidTypeException {
long longValue = (long)value;
if (longValue != value) {
throw new InvalidTypeException("Can't convert " + value + " to long");
} else {
return super.checkedLongValue();
}
}
float checkedFloatValue() throws InvalidTypeException {
float floatValue = (float)value;
if (floatValue != value) {
throw new InvalidTypeException("Can't convert " + value + " to float");
} else {
return super.checkedFloatValue();
}
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.DOUBLE;
}
}

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 1998, 2006, 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 com.sun.jdi.event.EventQueue;
import com.sun.jdi.event.EventSet;
import java.util.*;
public class EventQueueImpl extends MirrorImpl implements EventQueue {
/*
* Note this is not a synchronized list. Iteration/update should be
* protected through the 'this' monitor.
*/
LinkedList<EventSet> eventSets = new LinkedList<EventSet>();
TargetVM target;
boolean closed = false;
EventQueueImpl(VirtualMachine vm, TargetVM target) {
super(vm);
this.target = target;
target.addEventQueue(this);
}
/*
* Override superclass back to default equality
*/
public boolean equals(Object obj) {
return this == obj;
}
public int hashCode() {
return System.identityHashCode(this);
}
synchronized void enqueue(EventSet eventSet) {
eventSets.add(eventSet);
notifyAll();
}
synchronized int size() {
return eventSets.size();
}
synchronized void close() {
if (!closed) {
closed = true; // OK for this the be first since synchronized
// place VMDisconnectEvent into queue
enqueue(new EventSetImpl(vm,
(byte)JDWP.EventKind.VM_DISCONNECTED));
}
}
public EventSet remove() throws InterruptedException {
return remove(0);
}
/**
* Filter out events not for user's eyes.
* Then filter out empty sets.
*/
public EventSet remove(long timeout) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("Timeout cannot be negative");
}
EventSet eventSet;
while (true) {
EventSetImpl fullEventSet = removeUnfiltered(timeout);
if (fullEventSet == null) {
eventSet = null; // timeout
break;
}
/*
* Remove events from the event set for which
* there is no corresponding enabled request (
* this includes our internally requested events.)
* This never returns null
*/
eventSet = fullEventSet.userFilter();
if (!eventSet.isEmpty()) {
break;
}
}
if ((eventSet != null) && (eventSet.suspendPolicy() == JDWP.SuspendPolicy.ALL)) {
vm.notifySuspend();
}
return eventSet;
}
EventSet removeInternal() throws InterruptedException {
EventSet eventSet;
do {
// Waiting forever, so removeUnfiltered() is never null
eventSet = removeUnfiltered(0).internalFilter();
} while (eventSet == null || eventSet.isEmpty());
/*
* Currently, no internal events are requested with a suspend
* policy other than none, so we don't check for notifySuspend()
* here. If this changes in the future, there is much
* infrastructure that needs to be updated.
*/
return eventSet;
}
private TimerThread startTimerThread(long timeout) {
TimerThread thread = new TimerThread(timeout);
thread.setDaemon(true);
thread.start();
return thread;
}
private boolean shouldWait(TimerThread timerThread) {
return !closed && eventSets.isEmpty() &&
((timerThread == null) ? true : !timerThread.timedOut());
}
private EventSetImpl removeUnfiltered(long timeout)
throws InterruptedException {
EventSetImpl eventSet = null;
/*
* Make sure the VM has completed initialization before
* trying to build events.
*/
vm.waitInitCompletion();
synchronized(this) {
if (!eventSets.isEmpty()) {
/*
* If there's already something there, no need
* for anything elaborate.
*/
eventSet = (EventSetImpl)eventSets.removeFirst();
} else {
/*
* If a timeout was specified, create a thread to
* notify this one when a timeout
* occurs. We can't use the timed version of wait()
* because it is possible for multiple enqueue() calls
* before we see something in the eventSet queue
* (this is possible when multiple threads call
* remove() concurrently -- not a great idea, but
* it should be supported). Even if enqueue() did a
* notify() instead of notifyAll() we are not able to
* use a timed wait because there's no way to distinguish
* a timeout from a notify. That limitation implies a
* possible race condition between a timed out thread
* and a notified thread.
*/
TimerThread timerThread = null;
try {
if (timeout > 0) {
timerThread = startTimerThread(timeout);
}
while (shouldWait(timerThread)) {
this.wait();
}
} finally {
if ((timerThread != null) && !timerThread.timedOut()) {
timerThread.interrupt();
}
}
if (eventSets.isEmpty()) {
if (closed) {
throw new VMDisconnectedException();
}
} else {
eventSet = (EventSetImpl)eventSets.removeFirst();
}
}
}
// The build is synchronized on the event set, don't hold
// the queue lock.
if (eventSet != null) {
target.notifyDequeueEventSet();
eventSet.build();
}
return eventSet;
}
private class TimerThread extends Thread {
private boolean timedOut = false;
private long timeout;
TimerThread(long timeout) {
super(vm.threadGroupForJDI(), "JDI Event Queue Timer");
this.timeout = timeout;
}
boolean timedOut() {
return timedOut;
}
public void run() {
try {
Thread.sleep(timeout);
EventQueueImpl queue = EventQueueImpl.this;
synchronized(queue) {
timedOut = true;
queue.notifyAll();
}
} catch (InterruptedException e) {
// Exit without notifying
}
}
}
}

View File

@@ -0,0 +1,954 @@
/*
* 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 com.sun.jdi.request.*;
import com.sun.tools.jdi.JDWP;
import java.util.*;
/**
* This interface is used to create and remove Breakpoints, Watchpoints,
* etc.
* It include implementations of all the request interfaces..
*/
// Warnings from List filters and List[] requestLists is hard to fix.
// Remove SuppressWarning when we fix the warnings from List filters
// and List[] requestLists. The generic array is not supported.
@SuppressWarnings("unchecked")
class EventRequestManagerImpl extends MirrorImpl
implements EventRequestManager
{
List<? extends EventRequest>[] requestLists;
private static int methodExitEventCmd = 0;
static int JDWPtoJDISuspendPolicy(byte jdwpPolicy) {
switch(jdwpPolicy) {
case JDWP.SuspendPolicy.ALL:
return EventRequest.SUSPEND_ALL;
case JDWP.SuspendPolicy.EVENT_THREAD:
return EventRequest.SUSPEND_EVENT_THREAD;
case JDWP.SuspendPolicy.NONE:
return EventRequest.SUSPEND_NONE;
default:
throw new IllegalArgumentException("Illegal policy constant: " + jdwpPolicy);
}
}
static byte JDItoJDWPSuspendPolicy(int jdiPolicy) {
switch(jdiPolicy) {
case EventRequest.SUSPEND_ALL:
return JDWP.SuspendPolicy.ALL;
case EventRequest.SUSPEND_EVENT_THREAD:
return JDWP.SuspendPolicy.EVENT_THREAD;
case EventRequest.SUSPEND_NONE:
return JDWP.SuspendPolicy.NONE;
default:
throw new IllegalArgumentException("Illegal policy constant: " + jdiPolicy);
}
}
/*
* Override superclass back to default equality
*/
public boolean equals(Object obj) {
return this == obj;
}
public int hashCode() {
return System.identityHashCode(this);
}
abstract class EventRequestImpl extends MirrorImpl implements EventRequest {
int id;
/*
* This list is not protected by a synchronized wrapper. All
* access/modification should be protected by synchronizing on
* the enclosing instance of EventRequestImpl.
*/
List<Object> filters = new ArrayList<>();
boolean isEnabled = false;
boolean deleted = false;
byte suspendPolicy = JDWP.SuspendPolicy.ALL;
private Map<Object, Object> clientProperties = null;
EventRequestImpl() {
super(EventRequestManagerImpl.this.vm);
}
/*
* Override superclass back to default equality
*/
public boolean equals(Object obj) {
return this == obj;
}
public int hashCode() {
return System.identityHashCode(this);
}
abstract int eventCmd();
InvalidRequestStateException invalidState() {
return new InvalidRequestStateException(toString());
}
String state() {
return deleted? " (deleted)" :
(isEnabled()? " (enabled)" : " (disabled)");
}
/**
* @return all the event request of this kind
*/
List requestList() {
return EventRequestManagerImpl.this.requestList(eventCmd());
}
/**
* delete the event request
*/
void delete() {
if (!deleted) {
requestList().remove(this);
disable(); /* must do BEFORE delete */
deleted = true;
}
}
public boolean isEnabled() {
return isEnabled;
}
public void enable() {
setEnabled(true);
}
public void disable() {
setEnabled(false);
}
public synchronized void setEnabled(boolean val) {
if (deleted) {
throw invalidState();
} else {
if (val != isEnabled) {
if (isEnabled) {
clear();
} else {
set();
}
}
}
}
public synchronized void addCountFilter(int count) {
if (isEnabled() || deleted) {
throw invalidState();
}
if (count < 1) {
throw new IllegalArgumentException("count is less than one");
}
filters.add(JDWP.EventRequest.Set.Modifier.Count.create(count));
}
public void setSuspendPolicy(int policy) {
if (isEnabled() || deleted) {
throw invalidState();
}
suspendPolicy = JDItoJDWPSuspendPolicy(policy);
}
public int suspendPolicy() {
return JDWPtoJDISuspendPolicy(suspendPolicy);
}
/**
* set (enable) the event request
*/
synchronized void set() {
JDWP.EventRequest.Set.Modifier[] mods =
filters.toArray(
new JDWP.EventRequest.Set.Modifier[filters.size()]);
try {
id = JDWP.EventRequest.Set.process(vm, (byte)eventCmd(),
suspendPolicy, mods).requestID;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
isEnabled = true;
}
synchronized void clear() {
try {
JDWP.EventRequest.Clear.process(vm, (byte)eventCmd(), id);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
isEnabled = false;
}
/**
* @return a small Map
* @see #putProperty
* @see #getProperty
*/
private Map<Object, Object> getProperties() {
if (clientProperties == null) {
clientProperties = new HashMap<Object, Object>(2);
}
return clientProperties;
}
/**
* Returns the value of the property with the specified key. Only
* properties added with <code>putProperty</code> will return
* a non-null value.
*
* @return the value of this property or null
* @see #putProperty
*/
public final Object getProperty(Object key) {
if (clientProperties == null) {
return null;
} else {
return getProperties().get(key);
}
}
/**
* Add an arbitrary key/value "property" to this component.
*
* @see #getProperty
*/
public final void putProperty(Object key, Object value) {
if (value != null) {
getProperties().put(key, value);
} else {
getProperties().remove(key);
}
}
}
abstract class ThreadVisibleEventRequestImpl extends EventRequestImpl {
public synchronized void addThreadFilter(ThreadReference thread) {
validateMirror(thread);
if (isEnabled() || deleted) {
throw invalidState();
}
filters.add(JDWP.EventRequest.Set.Modifier.ThreadOnly
.create((ThreadReferenceImpl)thread));
}
}
abstract class ClassVisibleEventRequestImpl
extends ThreadVisibleEventRequestImpl {
public synchronized void addClassFilter(ReferenceType clazz) {
validateMirror(clazz);
if (isEnabled() || deleted) {
throw invalidState();
}
filters.add(JDWP.EventRequest.Set.Modifier.ClassOnly
.create((ReferenceTypeImpl)clazz));
}
public synchronized void addClassFilter(String classPattern) {
if (isEnabled() || deleted) {
throw invalidState();
}
if (classPattern == null) {
throw new NullPointerException();
}
filters.add(JDWP.EventRequest.Set.Modifier.ClassMatch
.create(classPattern));
}
public synchronized void addClassExclusionFilter(String classPattern) {
if (isEnabled() || deleted) {
throw invalidState();
}
if (classPattern == null) {
throw new NullPointerException();
}
filters.add(JDWP.EventRequest.Set.Modifier.ClassExclude
.create(classPattern));
}
public synchronized void addInstanceFilter(ObjectReference instance) {
validateMirror(instance);
if (isEnabled() || deleted) {
throw invalidState();
}
if (!vm.canUseInstanceFilters()) {
throw new UnsupportedOperationException(
"target does not support instance filters");
}
filters.add(JDWP.EventRequest.Set.Modifier.InstanceOnly
.create((ObjectReferenceImpl)instance));
}
}
class BreakpointRequestImpl extends ClassVisibleEventRequestImpl
implements BreakpointRequest {
private final Location location;
BreakpointRequestImpl(Location location) {
this.location = location;
filters.add(0,JDWP.EventRequest.Set.Modifier.LocationOnly
.create(location));
requestList().add(this);
}
public Location location() {
return location;
}
int eventCmd() {
return JDWP.EventKind.BREAKPOINT;
}
public String toString() {
return "breakpoint request " + location() + state();
}
}
class ClassPrepareRequestImpl extends ClassVisibleEventRequestImpl
implements ClassPrepareRequest {
ClassPrepareRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.CLASS_PREPARE;
}
public synchronized void addSourceNameFilter(String sourceNamePattern) {
if (isEnabled() || deleted) {
throw invalidState();
}
if (!vm.canUseSourceNameFilters()) {
throw new UnsupportedOperationException(
"target does not support source name filters");
}
if (sourceNamePattern == null) {
throw new NullPointerException();
}
filters.add(JDWP.EventRequest.Set.Modifier.SourceNameMatch
.create(sourceNamePattern));
}
public String toString() {
return "class prepare request " + state();
}
}
class ClassUnloadRequestImpl extends ClassVisibleEventRequestImpl
implements ClassUnloadRequest {
ClassUnloadRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.CLASS_UNLOAD;
}
public String toString() {
return "class unload request " + state();
}
}
class ExceptionRequestImpl extends ClassVisibleEventRequestImpl
implements ExceptionRequest {
ReferenceType exception = null;
boolean caught = true;
boolean uncaught = true;
ExceptionRequestImpl(ReferenceType refType,
boolean notifyCaught, boolean notifyUncaught) {
exception = refType;
caught = notifyCaught;
uncaught = notifyUncaught;
{
ReferenceTypeImpl exc;
if (exception == null) {
exc = new ClassTypeImpl(vm, 0);
} else {
exc = (ReferenceTypeImpl)exception;
}
filters.add(JDWP.EventRequest.Set.Modifier.ExceptionOnly.
create(exc, caught, uncaught));
}
requestList().add(this);
}
public ReferenceType exception() {
return exception;
}
public boolean notifyCaught() {
return caught;
}
public boolean notifyUncaught() {
return uncaught;
}
int eventCmd() {
return JDWP.EventKind.EXCEPTION;
}
public String toString() {
return "exception request " + exception() + state();
}
}
class MethodEntryRequestImpl extends ClassVisibleEventRequestImpl
implements MethodEntryRequest {
MethodEntryRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.METHOD_ENTRY;
}
public String toString() {
return "method entry request " + state();
}
}
class MethodExitRequestImpl extends ClassVisibleEventRequestImpl
implements MethodExitRequest {
MethodExitRequestImpl() {
if (methodExitEventCmd == 0) {
/*
* If we can get return values, then we always get them.
* Thus, for JDI MethodExitRequests, we always use the
* same JDWP EventKind. Here we decide which to use and
* save it so that it will be used for all future
* MethodExitRequests.
*
* This call to canGetMethodReturnValues can't
* be done in the EventRequestManager ctor because that is too early.
*/
if (vm.canGetMethodReturnValues()) {
methodExitEventCmd = JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE;
} else {
methodExitEventCmd = JDWP.EventKind.METHOD_EXIT;
}
}
requestList().add(this);
}
int eventCmd() {
return EventRequestManagerImpl.methodExitEventCmd;
}
public String toString() {
return "method exit request " + state();
}
}
class MonitorContendedEnterRequestImpl extends ClassVisibleEventRequestImpl
implements MonitorContendedEnterRequest {
MonitorContendedEnterRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.MONITOR_CONTENDED_ENTER;
}
public String toString() {
return "monitor contended enter request " + state();
}
}
class MonitorContendedEnteredRequestImpl extends ClassVisibleEventRequestImpl
implements MonitorContendedEnteredRequest {
MonitorContendedEnteredRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.MONITOR_CONTENDED_ENTERED;
}
public String toString() {
return "monitor contended entered request " + state();
}
}
class MonitorWaitRequestImpl extends ClassVisibleEventRequestImpl
implements MonitorWaitRequest {
MonitorWaitRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.MONITOR_WAIT;
}
public String toString() {
return "monitor wait request " + state();
}
}
class MonitorWaitedRequestImpl extends ClassVisibleEventRequestImpl
implements MonitorWaitedRequest {
MonitorWaitedRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.MONITOR_WAITED;
}
public String toString() {
return "monitor waited request " + state();
}
}
class StepRequestImpl extends ClassVisibleEventRequestImpl
implements StepRequest {
ThreadReferenceImpl thread;
int size;
int depth;
StepRequestImpl(ThreadReference thread, int size, int depth) {
this.thread = (ThreadReferenceImpl)thread;
this.size = size;
this.depth = depth;
/*
* Translate size and depth to corresponding JDWP values.
*/
int jdwpSize;
switch (size) {
case STEP_MIN:
jdwpSize = JDWP.StepSize.MIN;
break;
case STEP_LINE:
jdwpSize = JDWP.StepSize.LINE;
break;
default:
throw new IllegalArgumentException("Invalid step size");
}
int jdwpDepth;
switch (depth) {
case STEP_INTO:
jdwpDepth = JDWP.StepDepth.INTO;
break;
case STEP_OVER:
jdwpDepth = JDWP.StepDepth.OVER;
break;
case STEP_OUT:
jdwpDepth = JDWP.StepDepth.OUT;
break;
default:
throw new IllegalArgumentException("Invalid step depth");
}
/*
* Make sure this isn't a duplicate
*/
List<StepRequest> requests = stepRequests();
Iterator<StepRequest> iter = requests.iterator();
while (iter.hasNext()) {
StepRequest request = iter.next();
if ((request != this) &&
request.isEnabled() &&
request.thread().equals(thread)) {
throw new DuplicateRequestException(
"Only one step request allowed per thread");
}
}
filters.add(JDWP.EventRequest.Set.Modifier.Step.
create(this.thread, jdwpSize, jdwpDepth));
requestList().add(this);
}
public int depth() {
return depth;
}
public int size() {
return size;
}
public ThreadReference thread() {
return thread;
}
int eventCmd() {
return JDWP.EventKind.SINGLE_STEP;
}
public String toString() {
return "step request " + thread() + state();
}
}
class ThreadDeathRequestImpl extends ThreadVisibleEventRequestImpl
implements ThreadDeathRequest {
ThreadDeathRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.THREAD_DEATH;
}
public String toString() {
return "thread death request " + state();
}
}
class ThreadStartRequestImpl extends ThreadVisibleEventRequestImpl
implements ThreadStartRequest {
ThreadStartRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.THREAD_START;
}
public String toString() {
return "thread start request " + state();
}
}
abstract class WatchpointRequestImpl extends ClassVisibleEventRequestImpl
implements WatchpointRequest {
final Field field;
WatchpointRequestImpl(Field field) {
this.field = field;
filters.add(0,
JDWP.EventRequest.Set.Modifier.FieldOnly.create(
(ReferenceTypeImpl)field.declaringType(),
((FieldImpl)field).ref()));
}
public Field field() {
return field;
}
}
class AccessWatchpointRequestImpl extends WatchpointRequestImpl
implements AccessWatchpointRequest {
AccessWatchpointRequestImpl(Field field) {
super(field);
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.FIELD_ACCESS;
}
public String toString() {
return "access watchpoint request " + field + state();
}
}
class ModificationWatchpointRequestImpl extends WatchpointRequestImpl
implements ModificationWatchpointRequest {
ModificationWatchpointRequestImpl(Field field) {
super(field);
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.FIELD_MODIFICATION;
}
public String toString() {
return "modification watchpoint request " + field + state();
}
}
class VMDeathRequestImpl extends EventRequestImpl
implements VMDeathRequest {
VMDeathRequestImpl() {
requestList().add(this);
}
int eventCmd() {
return JDWP.EventKind.VM_DEATH;
}
public String toString() {
return "VM death request " + state();
}
}
/**
* Constructor.
*/
EventRequestManagerImpl(VirtualMachine vm) {
super(vm);
java.lang.reflect.Field[] ekinds =
JDWP.EventKind.class.getDeclaredFields();
int highest = 0;
for (int i = 0; i < ekinds.length; ++i) {
int val;
try {
val = ekinds[i].getInt(null);
} catch (IllegalAccessException exc) {
throw new RuntimeException("Got: " + exc);
}
if (val > highest) {
highest = val;
}
}
requestLists = new List[highest+1];
for (int i=0; i <= highest; i++) {
requestLists[i] = new ArrayList<>();
}
}
public ClassPrepareRequest createClassPrepareRequest() {
return new ClassPrepareRequestImpl();
}
public ClassUnloadRequest createClassUnloadRequest() {
return new ClassUnloadRequestImpl();
}
public ExceptionRequest createExceptionRequest(ReferenceType refType,
boolean notifyCaught,
boolean notifyUncaught) {
validateMirrorOrNull(refType);
return new ExceptionRequestImpl(refType, notifyCaught, notifyUncaught);
}
public StepRequest createStepRequest(ThreadReference thread,
int size, int depth) {
validateMirror(thread);
return new StepRequestImpl(thread, size, depth);
}
public ThreadDeathRequest createThreadDeathRequest() {
return new ThreadDeathRequestImpl();
}
public ThreadStartRequest createThreadStartRequest() {
return new ThreadStartRequestImpl();
}
public MethodEntryRequest createMethodEntryRequest() {
return new MethodEntryRequestImpl();
}
public MethodExitRequest createMethodExitRequest() {
return new MethodExitRequestImpl();
}
public MonitorContendedEnterRequest createMonitorContendedEnterRequest() {
if (!vm.canRequestMonitorEvents()) {
throw new UnsupportedOperationException(
"target VM does not support requesting Monitor events");
}
return new MonitorContendedEnterRequestImpl();
}
public MonitorContendedEnteredRequest createMonitorContendedEnteredRequest() {
if (!vm.canRequestMonitorEvents()) {
throw new UnsupportedOperationException(
"target VM does not support requesting Monitor events");
}
return new MonitorContendedEnteredRequestImpl();
}
public MonitorWaitRequest createMonitorWaitRequest() {
if (!vm.canRequestMonitorEvents()) {
throw new UnsupportedOperationException(
"target VM does not support requesting Monitor events");
}
return new MonitorWaitRequestImpl();
}
public MonitorWaitedRequest createMonitorWaitedRequest() {
if (!vm.canRequestMonitorEvents()) {
throw new UnsupportedOperationException(
"target VM does not support requesting Monitor events");
}
return new MonitorWaitedRequestImpl();
}
public BreakpointRequest createBreakpointRequest(Location location) {
validateMirror(location);
if (location.codeIndex() == -1) {
throw new NativeMethodException("Cannot set breakpoints on native methods");
}
return new BreakpointRequestImpl(location);
}
public AccessWatchpointRequest
createAccessWatchpointRequest(Field field) {
validateMirror(field);
if (!vm.canWatchFieldAccess()) {
throw new UnsupportedOperationException(
"target VM does not support access watchpoints");
}
return new AccessWatchpointRequestImpl(field);
}
public ModificationWatchpointRequest
createModificationWatchpointRequest(Field field) {
validateMirror(field);
if (!vm.canWatchFieldModification()) {
throw new UnsupportedOperationException(
"target VM does not support modification watchpoints");
}
return new ModificationWatchpointRequestImpl(field);
}
public VMDeathRequest createVMDeathRequest() {
if (!vm.canRequestVMDeathEvent()) {
throw new UnsupportedOperationException(
"target VM does not support requesting VM death events");
}
return new VMDeathRequestImpl();
}
public void deleteEventRequest(EventRequest eventRequest) {
validateMirror(eventRequest);
((EventRequestImpl)eventRequest).delete();
}
public void deleteEventRequests(List<? extends EventRequest> eventRequests) {
validateMirrors(eventRequests);
// copy the eventRequests to avoid ConcurrentModificationException
Iterator<? extends EventRequest> iter = (new ArrayList<>(eventRequests)).iterator();
while (iter.hasNext()) {
((EventRequestImpl)iter.next()).delete();
}
}
public void deleteAllBreakpoints() {
requestList(JDWP.EventKind.BREAKPOINT).clear();
try {
JDWP.EventRequest.ClearAllBreakpoints.process(vm);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
public List<StepRequest> stepRequests() {
return (List<StepRequest>)unmodifiableRequestList(JDWP.EventKind.SINGLE_STEP);
}
public List<ClassPrepareRequest> classPrepareRequests() {
return (List<ClassPrepareRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_PREPARE);
}
public List<ClassUnloadRequest> classUnloadRequests() {
return (List<ClassUnloadRequest>)unmodifiableRequestList(JDWP.EventKind.CLASS_UNLOAD);
}
public List<ThreadStartRequest> threadStartRequests() {
return (List<ThreadStartRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_START);
}
public List<ThreadDeathRequest> threadDeathRequests() {
return (List<ThreadDeathRequest>)unmodifiableRequestList(JDWP.EventKind.THREAD_DEATH);
}
public List<ExceptionRequest> exceptionRequests() {
return (List<ExceptionRequest>)unmodifiableRequestList(JDWP.EventKind.EXCEPTION);
}
public List<BreakpointRequest> breakpointRequests() {
return (List<BreakpointRequest>)unmodifiableRequestList(JDWP.EventKind.BREAKPOINT);
}
public List<AccessWatchpointRequest> accessWatchpointRequests() {
return (List<AccessWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_ACCESS);
}
public List<ModificationWatchpointRequest> modificationWatchpointRequests() {
return (List<ModificationWatchpointRequest>)unmodifiableRequestList(JDWP.EventKind.FIELD_MODIFICATION);
}
public List<MethodEntryRequest> methodEntryRequests() {
return (List<MethodEntryRequest>)unmodifiableRequestList(JDWP.EventKind.METHOD_ENTRY);
}
public List<MethodExitRequest> methodExitRequests() {
return (List<MethodExitRequest>)unmodifiableRequestList(
EventRequestManagerImpl.methodExitEventCmd);
}
public List<MonitorContendedEnterRequest> monitorContendedEnterRequests() {
return (List<MonitorContendedEnterRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTER);
}
public List<MonitorContendedEnteredRequest> monitorContendedEnteredRequests() {
return (List<MonitorContendedEnteredRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_CONTENDED_ENTERED);
}
public List<MonitorWaitRequest> monitorWaitRequests() {
return (List<MonitorWaitRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAIT);
}
public List<MonitorWaitedRequest> monitorWaitedRequests() {
return (List<MonitorWaitedRequest>)unmodifiableRequestList(JDWP.EventKind.MONITOR_WAITED);
}
public List<VMDeathRequest> vmDeathRequests() {
return (List<VMDeathRequest>)unmodifiableRequestList(JDWP.EventKind.VM_DEATH);
}
List<? extends EventRequest> unmodifiableRequestList(int eventCmd) {
return Collections.unmodifiableList(requestList(eventCmd));
}
EventRequest request(int eventCmd, int requestId) {
List<? extends EventRequest> rl = requestList(eventCmd);
for (int i = rl.size() - 1; i >= 0; i--) {
EventRequestImpl er = (EventRequestImpl)rl.get(i);
if (er.id == requestId) {
return er;
}
}
return null;
}
List<? extends EventRequest> requestList(int eventCmd) {
return requestLists[eventCmd];
}
}

View File

@@ -0,0 +1,879 @@
/*
* Copyright (c) 1998, 2013, 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 com.sun.jdi.event.*;
import com.sun.jdi.request.*;
import java.util.*;
enum EventDestination {UNKNOWN_EVENT, INTERNAL_EVENT, CLIENT_EVENT};
/*
* An EventSet is normally created by the transport reader thread when
* it reads a JDWP Composite command. The constructor doesn't unpack
* the events contained in the Composite command and create EventImpls
* for them because that process might involve calling back into the back-end
* which should not be done by the transport reader thread. Instead,
* the raw bytes of the packet are read and stored in the EventSet.
* The EventSet is then added to each EventQueue. When an EventSet is
* removed from an EventQueue, the EventSetImpl.build() method is called.
* This method reads the packet bytes and creates the actual EventImpl objects.
* build() also filters out events for our internal handler and puts them in
* their own EventSet. This means that the EventImpls that are in the EventSet
* that is on the queues are all for client requests.
*/
public class EventSetImpl extends ArrayList<Event> implements EventSet {
private static final long serialVersionUID = -4857338819787924570L;
private VirtualMachineImpl vm; // we implement Mirror
private Packet pkt;
private byte suspendPolicy;
private EventSetImpl internalEventSet;
public String toString() {
String string = "event set, policy:" + suspendPolicy +
", count:" + this.size() + " = {";
boolean first = true;
for (Event event : this) {
if (!first) {
string += ", ";
}
string += event.toString();
first = false;
}
string += "}";
return string;
}
abstract class EventImpl extends MirrorImpl implements Event {
private final byte eventCmd;
private final int requestID;
// This is set only for client requests, not internal requests.
private final EventRequest request;
/**
* Constructor for events.
*/
protected EventImpl(JDWP.Event.Composite.Events.EventsCommon evt,
int requestID) {
super(EventSetImpl.this.vm);
this.eventCmd = evt.eventKind();
this.requestID = requestID;
EventRequestManagerImpl ermi = EventSetImpl.this.
vm.eventRequestManagerImpl();
this.request = ermi.request(eventCmd, requestID);
}
/*
* Override superclass back to default equality
*/
public boolean equals(Object obj) {
return this == obj;
}
public int hashCode() {
return System.identityHashCode(this);
}
/**
* Constructor for VM disconnected events.
*/
protected EventImpl(byte eventCmd) {
super(EventSetImpl.this.vm);
this.eventCmd = eventCmd;
this.requestID = 0;
this.request = null;
}
public EventRequest request() {
return request;
}
int requestID() {
return requestID;
}
EventDestination destination() {
/*
* We need to decide if this event is for
* 1. an internal request
* 2. a client request that is no longer available, ie
* it has been deleted, or disabled and re-enabled
* which gives it a new ID.
* 3. a current client request that is disabled
* 4. a current enabled client request.
*
* We will filter this set into a set
* that contains only 1s for our internal queue
* and a set that contains only 4s for our client queue.
* If we get an EventSet that contains only 2 and 3
* then we have to resume it if it is not SUSPEND_NONE
* because no one else will.
*/
if (requestID == 0) {
/* An unsolicited event. These have traditionally
* been treated as client events.
*/
return EventDestination.CLIENT_EVENT;
}
// Is this an event for a current client request?
if (request == null) {
// Nope. Is it an event for an internal request?
EventRequestManagerImpl ermi = this.vm.getInternalEventRequestManager();
if (ermi.request(eventCmd, requestID) != null) {
// Yep
return EventDestination.INTERNAL_EVENT;
}
return EventDestination.UNKNOWN_EVENT;
}
// We found a client request
if (request.isEnabled()) {
return EventDestination.CLIENT_EVENT;
}
return EventDestination.UNKNOWN_EVENT;
}
abstract String eventName();
public String toString() {
return eventName();
}
}
abstract class ThreadedEventImpl extends EventImpl {
private ThreadReference thread;
ThreadedEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,
int requestID, ThreadReference thread) {
super(evt, requestID);
this.thread = thread;
}
public ThreadReference thread() {
return thread;
}
public String toString() {
return eventName() + " in thread " + thread.name();
}
}
abstract class LocatableEventImpl extends ThreadedEventImpl
implements Locatable {
private Location location;
LocatableEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,
int requestID,
ThreadReference thread, Location location) {
super(evt, requestID, thread);
this.location = location;
}
public Location location() {
return location;
}
/**
* For MethodEntry and MethodExit
*/
public Method method() {
return location.method();
}
public String toString() {
return eventName() + "@" +
((location() == null) ? " null" : location().toString()) +
" in thread " + thread().name();
}
}
class BreakpointEventImpl extends LocatableEventImpl
implements BreakpointEvent {
BreakpointEventImpl(JDWP.Event.Composite.Events.Breakpoint evt) {
super(evt, evt.requestID, evt.thread, evt.location);
}
String eventName() {
return "BreakpointEvent";
}
}
class StepEventImpl extends LocatableEventImpl implements StepEvent {
StepEventImpl(JDWP.Event.Composite.Events.SingleStep evt) {
super(evt, evt.requestID, evt.thread, evt.location);
}
String eventName() {
return "StepEvent";
}
}
class MethodEntryEventImpl extends LocatableEventImpl
implements MethodEntryEvent {
MethodEntryEventImpl(JDWP.Event.Composite.Events.MethodEntry evt) {
super(evt, evt.requestID, evt.thread, evt.location);
}
String eventName() {
return "MethodEntryEvent";
}
}
class MethodExitEventImpl extends LocatableEventImpl
implements MethodExitEvent {
private Value returnVal = null;
MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExit evt) {
super(evt, evt.requestID, evt.thread, evt.location);
}
MethodExitEventImpl(JDWP.Event.Composite.Events.MethodExitWithReturnValue evt) {
super(evt, evt.requestID, evt.thread, evt.location);
returnVal = evt.value;
}
String eventName() {
return "MethodExitEvent";
}
public Value returnValue() {
if (!this.vm.canGetMethodReturnValues()) {
throw new UnsupportedOperationException(
"target does not support return values in MethodExit events");
}
return returnVal;
}
}
class MonitorContendedEnterEventImpl extends LocatableEventImpl
implements MonitorContendedEnterEvent {
private ObjectReference monitor = null;
MonitorContendedEnterEventImpl(JDWP.Event.Composite.Events.MonitorContendedEnter evt) {
super(evt, evt.requestID, evt.thread, evt.location);
this.monitor = evt.object;
}
String eventName() {
return "MonitorContendedEnter";
}
public ObjectReference monitor() {
return monitor;
};
}
class MonitorContendedEnteredEventImpl extends LocatableEventImpl
implements MonitorContendedEnteredEvent {
private ObjectReference monitor = null;
MonitorContendedEnteredEventImpl(JDWP.Event.Composite.Events.MonitorContendedEntered evt) {
super(evt, evt.requestID, evt.thread, evt.location);
this.monitor = evt.object;
}
String eventName() {
return "MonitorContendedEntered";
}
public ObjectReference monitor() {
return monitor;
};
}
class MonitorWaitEventImpl extends LocatableEventImpl
implements MonitorWaitEvent {
private ObjectReference monitor = null;
private long timeout;
MonitorWaitEventImpl(JDWP.Event.Composite.Events.MonitorWait evt) {
super(evt, evt.requestID, evt.thread, evt.location);
this.monitor = evt.object;
this.timeout = evt.timeout;
}
String eventName() {
return "MonitorWait";
}
public ObjectReference monitor() {
return monitor;
};
public long timeout() {
return timeout;
}
}
class MonitorWaitedEventImpl extends LocatableEventImpl
implements MonitorWaitedEvent {
private ObjectReference monitor = null;
private boolean timed_out;
MonitorWaitedEventImpl(JDWP.Event.Composite.Events.MonitorWaited evt) {
super(evt, evt.requestID, evt.thread, evt.location);
this.monitor = evt.object;
this.timed_out = evt.timed_out;
}
String eventName() {
return "MonitorWaited";
}
public ObjectReference monitor() {
return monitor;
};
public boolean timedout() {
return timed_out;
}
}
class ClassPrepareEventImpl extends ThreadedEventImpl
implements ClassPrepareEvent {
private ReferenceType referenceType;
ClassPrepareEventImpl(JDWP.Event.Composite.Events.ClassPrepare evt) {
super(evt, evt.requestID, evt.thread);
referenceType = this.vm.referenceType(evt.typeID, evt.refTypeTag,
evt.signature);
((ReferenceTypeImpl)referenceType).setStatus(evt.status);
}
public ReferenceType referenceType() {
return referenceType;
}
String eventName() {
return "ClassPrepareEvent";
}
}
class ClassUnloadEventImpl extends EventImpl implements ClassUnloadEvent {
private String classSignature;
ClassUnloadEventImpl(JDWP.Event.Composite.Events.ClassUnload evt) {
super(evt, evt.requestID);
this.classSignature = evt.signature;
}
public String className() {
return classSignature.substring(1, classSignature.length()-1)
.replace('/', '.');
}
public String classSignature() {
return classSignature;
}
String eventName() {
return "ClassUnloadEvent";
}
}
class ExceptionEventImpl extends LocatableEventImpl
implements ExceptionEvent {
private ObjectReference exception;
private Location catchLocation;
ExceptionEventImpl(JDWP.Event.Composite.Events.Exception evt) {
super(evt, evt.requestID, evt.thread, evt.location);
this.exception = evt.exception;
this.catchLocation = evt.catchLocation;
}
public ObjectReference exception() {
return exception;
}
public Location catchLocation() {
return catchLocation;
}
String eventName() {
return "ExceptionEvent";
}
}
class ThreadDeathEventImpl extends ThreadedEventImpl
implements ThreadDeathEvent {
ThreadDeathEventImpl(JDWP.Event.Composite.Events.ThreadDeath evt) {
super(evt, evt.requestID, evt.thread);
}
String eventName() {
return "ThreadDeathEvent";
}
}
class ThreadStartEventImpl extends ThreadedEventImpl
implements ThreadStartEvent {
ThreadStartEventImpl(JDWP.Event.Composite.Events.ThreadStart evt) {
super(evt, evt.requestID, evt.thread);
}
String eventName() {
return "ThreadStartEvent";
}
}
class VMStartEventImpl extends ThreadedEventImpl
implements VMStartEvent {
VMStartEventImpl(JDWP.Event.Composite.Events.VMStart evt) {
super(evt, evt.requestID, evt.thread);
}
String eventName() {
return "VMStartEvent";
}
}
class VMDeathEventImpl extends EventImpl implements VMDeathEvent {
VMDeathEventImpl(JDWP.Event.Composite.Events.VMDeath evt) {
super(evt, evt.requestID);
}
String eventName() {
return "VMDeathEvent";
}
}
class VMDisconnectEventImpl extends EventImpl
implements VMDisconnectEvent {
VMDisconnectEventImpl() {
super((byte)JDWP.EventKind.VM_DISCONNECTED);
}
String eventName() {
return "VMDisconnectEvent";
}
}
abstract class WatchpointEventImpl extends LocatableEventImpl
implements WatchpointEvent {
private final ReferenceTypeImpl refType;
private final long fieldID;
private final ObjectReference object;
private Field field = null;
WatchpointEventImpl(JDWP.Event.Composite.Events.EventsCommon evt,
int requestID,
ThreadReference thread, Location location,
byte refTypeTag, long typeID, long fieldID,
ObjectReference object) {
super(evt, requestID, thread, location);
this.refType = this.vm.referenceType(typeID, refTypeTag);
this.fieldID = fieldID;
this.object = object;
}
public Field field() {
if (field == null) {
field = refType.getFieldMirror(fieldID);
}
return field;
}
public ObjectReference object() {
return object;
}
public Value valueCurrent() {
if (object == null) {
return refType.getValue(field());
} else {
return object.getValue(field());
}
}
}
class AccessWatchpointEventImpl extends WatchpointEventImpl
implements AccessWatchpointEvent {
AccessWatchpointEventImpl(JDWP.Event.Composite.Events.FieldAccess evt) {
super(evt, evt.requestID, evt.thread, evt.location,
evt.refTypeTag, evt.typeID, evt.fieldID, evt.object);
}
String eventName() {
return "AccessWatchpoint";
}
}
class ModificationWatchpointEventImpl extends WatchpointEventImpl
implements ModificationWatchpointEvent {
Value newValue;
ModificationWatchpointEventImpl(
JDWP.Event.Composite.Events.FieldModification evt) {
super(evt, evt.requestID, evt.thread, evt.location,
evt.refTypeTag, evt.typeID, evt.fieldID, evt.object);
this.newValue = evt.valueToBe;
}
public Value valueToBe() {
return newValue;
}
String eventName() {
return "ModificationWatchpoint";
}
}
/**
* Events are constructed on the thread which reads all data from the
* transport. This means that the packet cannot be converted to real
* JDI objects as that may involve further communications with the
* back end which would deadlock.
*
* Hence the {@link #build()} method below called by EventQueue.
*/
EventSetImpl(VirtualMachine aVm, Packet pkt) {
super();
// From "MirrorImpl":
// Yes, its a bit of a hack. But by doing it this
// way, this is the only place we have to change
// typing to substitute a new impl.
vm = (VirtualMachineImpl)aVm;
this.pkt = pkt;
}
/**
* Constructor for special events like VM disconnected
*/
EventSetImpl(VirtualMachine aVm, byte eventCmd) {
this(aVm, null);
suspendPolicy = JDWP.SuspendPolicy.NONE;
switch (eventCmd) {
case JDWP.EventKind.VM_DISCONNECTED:
addEvent(new VMDisconnectEventImpl());
break;
default:
throw new InternalException("Bad singleton event code");
}
}
private void addEvent(EventImpl evt) {
// Note that this class has a public add method that throws
// an exception so that clients can't modify the EventSet
super.add(evt);
}
/*
* Complete the construction of an EventSet. This is called from
* an event handler thread. It upacks the JDWP events inside
* the packet and creates EventImpls for them. The EventSet is already
* on EventQueues when this is called, so it has to be synch.
*/
synchronized void build() {
if (pkt == null) {
return;
}
PacketStream ps = new PacketStream(vm, pkt);
JDWP.Event.Composite compEvt = new JDWP.Event.Composite(vm, ps);
suspendPolicy = compEvt.suspendPolicy;
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
switch(suspendPolicy) {
case JDWP.SuspendPolicy.ALL:
vm.printTrace("EventSet: SUSPEND_ALL");
break;
case JDWP.SuspendPolicy.EVENT_THREAD:
vm.printTrace("EventSet: SUSPEND_EVENT_THREAD");
break;
case JDWP.SuspendPolicy.NONE:
vm.printTrace("EventSet: SUSPEND_NONE");
break;
}
}
ThreadReference fix6485605 = null;
for (int i = 0; i < compEvt.events.length; i++) {
EventImpl evt = createEvent(compEvt.events[i]);
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
try {
vm.printTrace("Event: " + evt);
} catch (VMDisconnectedException ee) {
// ignore - see bug 6502716
}
}
switch (evt.destination()) {
case UNKNOWN_EVENT:
// Ignore disabled, deleted, unknown events, but
// save the thread if there is one since we might
// have to resume it. Note that events for different
// threads can't be in the same event set.
if (evt instanceof ThreadedEventImpl &&
suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {
fix6485605 = ((ThreadedEventImpl)evt).thread();
}
continue;
case CLIENT_EVENT:
addEvent(evt);
break;
case INTERNAL_EVENT:
if (internalEventSet == null) {
internalEventSet = new EventSetImpl(this.vm, null);
}
internalEventSet.addEvent(evt);
break;
default:
throw new InternalException("Invalid event destination");
}
}
pkt = null; // No longer needed - free it up
// Avoid hangs described in 6296125, 6293795
if (super.size() == 0) {
// This set has no client events. If we don't do
// needed resumes, no one else is going to.
if (suspendPolicy == JDWP.SuspendPolicy.ALL) {
vm.resume();
} else if (suspendPolicy == JDWP.SuspendPolicy.EVENT_THREAD) {
// See bug 6485605.
if (fix6485605 != null) {
fix6485605.resume();
} else {
// apparently, there is nothing to resume.
}
}
suspendPolicy = JDWP.SuspendPolicy.NONE;
}
}
/**
* Filter out internal events
*/
EventSet userFilter() {
return this;
}
/**
* Filter out user events.
*/
EventSet internalFilter() {
return this.internalEventSet;
}
EventImpl createEvent(JDWP.Event.Composite.Events evt) {
JDWP.Event.Composite.Events.EventsCommon comm = evt.aEventsCommon;
switch (evt.eventKind) {
case JDWP.EventKind.THREAD_START:
return new ThreadStartEventImpl(
(JDWP.Event.Composite.Events.ThreadStart)comm);
case JDWP.EventKind.THREAD_END:
return new ThreadDeathEventImpl(
(JDWP.Event.Composite.Events.ThreadDeath)comm);
case JDWP.EventKind.EXCEPTION:
return new ExceptionEventImpl(
(JDWP.Event.Composite.Events.Exception)comm);
case JDWP.EventKind.BREAKPOINT:
return new BreakpointEventImpl(
(JDWP.Event.Composite.Events.Breakpoint)comm);
case JDWP.EventKind.METHOD_ENTRY:
return new MethodEntryEventImpl(
(JDWP.Event.Composite.Events.MethodEntry)comm);
case JDWP.EventKind.METHOD_EXIT:
return new MethodExitEventImpl(
(JDWP.Event.Composite.Events.MethodExit)comm);
case JDWP.EventKind.METHOD_EXIT_WITH_RETURN_VALUE:
return new MethodExitEventImpl(
(JDWP.Event.Composite.Events.MethodExitWithReturnValue)comm);
case JDWP.EventKind.FIELD_ACCESS:
return new AccessWatchpointEventImpl(
(JDWP.Event.Composite.Events.FieldAccess)comm);
case JDWP.EventKind.FIELD_MODIFICATION:
return new ModificationWatchpointEventImpl(
(JDWP.Event.Composite.Events.FieldModification)comm);
case JDWP.EventKind.SINGLE_STEP:
return new StepEventImpl(
(JDWP.Event.Composite.Events.SingleStep)comm);
case JDWP.EventKind.CLASS_PREPARE:
return new ClassPrepareEventImpl(
(JDWP.Event.Composite.Events.ClassPrepare)comm);
case JDWP.EventKind.CLASS_UNLOAD:
return new ClassUnloadEventImpl(
(JDWP.Event.Composite.Events.ClassUnload)comm);
case JDWP.EventKind.MONITOR_CONTENDED_ENTER:
return new MonitorContendedEnterEventImpl(
(JDWP.Event.Composite.Events.MonitorContendedEnter)comm);
case JDWP.EventKind.MONITOR_CONTENDED_ENTERED:
return new MonitorContendedEnteredEventImpl(
(JDWP.Event.Composite.Events.MonitorContendedEntered)comm);
case JDWP.EventKind.MONITOR_WAIT:
return new MonitorWaitEventImpl(
(JDWP.Event.Composite.Events.MonitorWait)comm);
case JDWP.EventKind.MONITOR_WAITED:
return new MonitorWaitedEventImpl(
(JDWP.Event.Composite.Events.MonitorWaited)comm);
case JDWP.EventKind.VM_START:
return new VMStartEventImpl(
(JDWP.Event.Composite.Events.VMStart)comm);
case JDWP.EventKind.VM_DEATH:
return new VMDeathEventImpl(
(JDWP.Event.Composite.Events.VMDeath)comm);
default:
// Ignore unknown event types
System.err.println("Ignoring event cmd " +
evt.eventKind + " from the VM");
return null;
}
}
public VirtualMachine virtualMachine() {
return vm;
}
public int suspendPolicy() {
return EventRequestManagerImpl.JDWPtoJDISuspendPolicy(suspendPolicy);
}
private ThreadReference eventThread() {
for (Event event : this) {
if (event instanceof ThreadedEventImpl) {
return ((ThreadedEventImpl)event).thread();
}
}
return null;
}
public void resume() {
switch (suspendPolicy()) {
case EventRequest.SUSPEND_ALL:
vm.resume();
break;
case EventRequest.SUSPEND_EVENT_THREAD:
ThreadReference thread = eventThread();
if (thread == null) {
throw new InternalException("Inconsistent suspend policy");
}
thread.resume();
break;
case EventRequest.SUSPEND_NONE:
// Do nothing
break;
default:
throw new InternalException("Invalid suspend policy");
}
}
public Iterator<Event> iterator() {
return new Itr();
}
public EventIterator eventIterator() {
return new Itr();
}
public class Itr implements EventIterator {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
public boolean hasNext() {
return cursor != size();
}
public Event next() {
try {
Event nxt = get(cursor);
++cursor;
return nxt;
} catch(IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
public Event nextEvent() {
return next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
@Override
public Spliterator<Event> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
/* below make this unmodifiable */
public boolean add(Event o){
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public boolean addAll(Collection<? extends Event> coll) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> coll) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 1998, 2004, 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.*;
public class FieldImpl extends TypeComponentImpl
implements Field, ValueContainer {
FieldImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
long ref,
String name, String signature,
String genericSignature, int modifiers) {
super(vm, declaringType, ref, name, signature,
genericSignature, modifiers);
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof FieldImpl)) {
FieldImpl other = (FieldImpl)obj;
return (declaringType().equals(other.declaringType())) &&
(ref() == other.ref()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
return (int)ref();
}
public int compareTo(Field field) {
ReferenceTypeImpl declaringType = (ReferenceTypeImpl)declaringType();
int rc = declaringType.compareTo(field.declaringType());
if (rc == 0) {
rc = declaringType.indexOf(this) -
declaringType.indexOf(field);
}
return rc;
}
public Type type() throws ClassNotLoadedException {
return findType(signature());
}
public Type findType(String signature) throws ClassNotLoadedException {
ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
return enclosing.findType(signature);
}
/**
* @return a text representation of the declared type
* of this field.
*/
public String typeName() {
JNITypeParser parser = new JNITypeParser(signature());
return parser.typeName();
}
public boolean isTransient() {
return isModifierSet(VMModifiers.TRANSIENT);
}
public boolean isVolatile() {
return isModifierSet(VMModifiers.VOLATILE);
}
public boolean isEnumConstant() {
return isModifierSet(VMModifiers.ENUM_CONSTANT);
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(declaringType().name());
buf.append('.');
buf.append(name());
return buf.toString();
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class FloatTypeImpl extends PrimitiveTypeImpl implements FloatType {
FloatTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.FLOAT);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedFloatValue());
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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.*;
public class FloatValueImpl extends PrimitiveValueImpl
implements FloatValue {
private float value;
FloatValueImpl(VirtualMachine aVm,float aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof FloatValue)) {
return (value == ((FloatValue)obj).value()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public int compareTo(FloatValue obj) {
float other = obj.value();
if (value() < other) {
return -1;
} else if (value() == other) {
return 0;
} else {
return 1;
}
}
public Type type() {
return vm.theFloatType();
}
public float value() {
return value;
}
public boolean booleanValue() {
return(value == 0.0)?false:true;
}
public byte byteValue() {
return(byte)value;
}
public char charValue() {
return(char)value;
}
public short shortValue() {
return(short)value;
}
public int intValue() {
return(int)value;
}
public long longValue() {
return(long)value;
}
public float floatValue() {
return value;
}
public double doubleValue() {
return(double)value;
}
byte checkedByteValue() throws InvalidTypeException {
if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to byte");
} else {
return super.checkedByteValue();
}
}
char checkedCharValue() throws InvalidTypeException {
if ((value > Character.MAX_VALUE) || (value < Character.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to char");
} else {
return super.checkedCharValue();
}
}
short checkedShortValue() throws InvalidTypeException {
if ((value > Short.MAX_VALUE) || (value < Short.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to short");
} else {
return super.checkedShortValue();
}
}
int checkedIntValue() throws InvalidTypeException {
int intValue = (int)value;
if (intValue != value) {
throw new InvalidTypeException("Can't convert " + value + " to int");
} else {
return super.checkedIntValue();
}
}
long checkedLongValue() throws InvalidTypeException {
long longValue = (long)value;
if (longValue != value) {
throw new InvalidTypeException("Can't convert " + value + " to long");
} else {
return super.checkedLongValue();
}
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.FLOAT;
}
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (c) 2003, 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 java.io.IOException;
import java.util.Map;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
/*
* An AttachingConnector to attach to a running VM using any
* TransportService.
*/
public class GenericAttachingConnector
extends ConnectorImpl implements AttachingConnector
{
/*
* The arguments that this connector supports
*/
static final String ARG_ADDRESS = "address";
static final String ARG_TIMEOUT = "timeout";
TransportService transportService;
Transport transport;
/*
* Initialize a new instance of this connector. The connector
* encapsulates a transport service and optionally has an
* "address" connector argument.
*/
private GenericAttachingConnector(TransportService ts,
boolean addAddressArgument)
{
transportService = ts;
transport = new Transport() {
public String name() {
// delegate name to the transport service
return transportService.name();
}
};
if (addAddressArgument) {
addStringArgument(
ARG_ADDRESS,
getString("generic_attaching.address.label"),
getString("generic_attaching.address"),
"",
true);
}
addIntegerArgument(
ARG_TIMEOUT,
getString("generic_attaching.timeout.label"),
getString("generic_attaching.timeout"),
"",
false,
0, Integer.MAX_VALUE);
}
/**
* Initializes a new instance of this connector. This constructor
* is used when sub-classing - the resulting connector will have
* a "timeout" connector argument.
*/
protected GenericAttachingConnector(TransportService ts) {
this(ts, false);
}
/*
* Create an instance of this connector. The resulting AttachingConnector
* will have address and timeout connector arguments.
*/
public static GenericAttachingConnector create(TransportService ts) {
return new GenericAttachingConnector(ts, true);
}
/**
* Attach to a target VM using the specified address and Connector arguments.
*/
public VirtualMachine attach(String address, Map<String, ? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String ts = argument(ARG_TIMEOUT, args).value();
int timeout = 0;
if (ts.length() > 0) {
timeout = Integer.decode(ts).intValue();
}
Connection connection = transportService.attach(address, timeout, 0);
return Bootstrap.virtualMachineManager().createVirtualMachine(connection);
}
/**
* Attach to a target VM using the specified arguments - the address
* of the target VM is specified by the <code>address</code> connector
* argument.
*/
public VirtualMachine
attach(Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String address = argument(ARG_ADDRESS, args).value();
return attach(address, args);
}
public String name() {
return transport.name() + "Attach";
}
public String description() {
return transportService.description();
}
public Transport transport() {
return transport;
}
}

View File

@@ -0,0 +1,187 @@
/*
* Copyright (c) 2003, 2018, 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 java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.IOException;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
/*
* A ListeningConnector to listen for connections from target VM
* using the configured transport service
*/
public class GenericListeningConnector
extends ConnectorImpl implements ListeningConnector
{
static final String ARG_ADDRESS = "address";
static final String ARG_TIMEOUT = "timeout";
Map<Map<String,? extends Connector.Argument>, TransportService.ListenKey> listenMap;
TransportService transportService;
Transport transport;
/**
* Initialize a new instance of this connector. The connector
* encapsulates a transport service, has a "timeout" connector argument,
* and optionally an "address" connector argument.
*/
private GenericListeningConnector(TransportService ts,
boolean addAddressArgument)
{
transportService = ts;
transport = new Transport() {
public String name() {
return transportService.name();
}
};
if (addAddressArgument) {
addStringArgument(
ARG_ADDRESS,
getString("generic_listening.address.label"),
getString("generic_listening.address"),
"",
false);
}
addIntegerArgument(
ARG_TIMEOUT,
getString("generic_listening.timeout.label"),
getString("generic_listening.timeout"),
"",
false,
0, Integer.MAX_VALUE);
listenMap = new HashMap<Map<String,? extends Connector.Argument>,TransportService.ListenKey>(10);
}
/**
* Initialize a new instance of this connector. This constructor is used
* when sub-classing - the resulting connector will a "timeout" connector
* argument.
*/
protected GenericListeningConnector(TransportService ts) {
this(ts, false);
}
/**
* Create an instance of this Connector. The resulting ListeningConnector will
* have "address" and "timeout" connector arguments.
*/
public static GenericListeningConnector create(TransportService ts) {
return new GenericListeningConnector(ts, true);
}
public String startListening(String address, Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
TransportService.ListenKey listener = listenMap.get(args);
if (listener != null) {
throw new IllegalConnectorArgumentsException("Already listening",
new ArrayList<String>(args.keySet()));
}
listener = transportService.startListening(address);
updateArgumentMapIfRequired(args, listener);
listenMap.put(args, listener);
return listener.address();
}
public String
startListening(Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String address = argument(ARG_ADDRESS, args).value();
return startListening(address, args);
}
public void stopListening(Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
TransportService.ListenKey listener = listenMap.get(args);
if (listener == null) {
throw new IllegalConnectorArgumentsException("Not listening",
new ArrayList<String>(args.keySet()));
}
transportService.stopListening(listener);
listenMap.remove(args);
}
public VirtualMachine
accept(Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String ts = argument(ARG_TIMEOUT, args).value();
int timeout = 0;
if (ts.length() > 0) {
timeout = Integer.decode(ts).intValue();
}
TransportService.ListenKey listener = listenMap.get(args);
Connection connection;
if (listener != null) {
connection = transportService.accept(listener, timeout, 0);
} else {
/*
* Keep compatibility with previous releases - if the
* debugger hasn't called startListening then we do a
* once-off accept
*/
startListening(args);
listener = listenMap.get(args);
assert listener != null;
connection = transportService.accept(listener, timeout, 0);
stopListening(args);
}
return Bootstrap.virtualMachineManager().createVirtualMachine(connection);
}
public boolean supportsMultipleConnections() {
return transportService.capabilities().supportsMultipleConnections();
}
public String name() {
return transport.name() + "Listen";
}
public String description() {
return transportService.description();
}
public Transport transport() {
return transport;
}
protected void updateArgumentMapIfRequired(
Map<String, ? extends Connector.Argument> args, TransportService.ListenKey listener) {
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class IntegerTypeImpl extends PrimitiveTypeImpl implements IntegerType {
IntegerTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.INT);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedIntValue());
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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.*;
public class IntegerValueImpl extends PrimitiveValueImpl
implements IntegerValue {
private int value;
IntegerValueImpl(VirtualMachine aVm,int aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof IntegerValue)) {
return (value == ((IntegerValue)obj).value()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public int compareTo(IntegerValue obj) {
int other = obj.value();
return (value()<other ? -1 : (value()==other ? 0 : 1));
}
public Type type() {
return vm.theIntegerType();
}
public int value() {
return value;
}
public boolean booleanValue() {
return(value == 0)?false:true;
}
public byte byteValue() {
return(byte)value;
}
public char charValue() {
return(char)value;
}
public short shortValue() {
return(short)value;
}
public int intValue() {
return value;
}
public long longValue() {
return(long)value;
}
public float floatValue() {
return(float)value;
}
public double doubleValue() {
return(double)value;
}
byte checkedByteValue() throws InvalidTypeException {
if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to byte");
} else {
return super.checkedByteValue();
}
}
char checkedCharValue() throws InvalidTypeException {
if ((value > Character.MAX_VALUE) || (value < Character.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to char");
} else {
return super.checkedCharValue();
}
}
short checkedShortValue() throws InvalidTypeException {
if ((value > Short.MAX_VALUE) || (value < Short.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to short");
} else {
return super.checkedShortValue();
}
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.INT;
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (c) 1998, 2015, 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.Collections;
import java.util.Set;
import java.lang.ref.SoftReference;
final public class InterfaceTypeImpl extends InvokableTypeImpl
implements InterfaceType {
private static class IResult implements InvocationResult {
final private JDWP.InterfaceType.InvokeMethod rslt;
public IResult(JDWP.InterfaceType.InvokeMethod rslt) {
this.rslt = rslt;
}
@Override
public ObjectReferenceImpl getException() {
return rslt.exception;
}
@Override
public ValueImpl getResult() {
return rslt.returnValue;
}
}
private SoftReference<List<InterfaceType>> superinterfacesRef = null;
protected InterfaceTypeImpl(VirtualMachine aVm,long aRef) {
super(aVm, aRef);
}
public List<InterfaceType> superinterfaces() {
List<InterfaceType> superinterfaces = (superinterfacesRef == null) ? null :
superinterfacesRef.get();
if (superinterfaces == null) {
superinterfaces = getInterfaces();
superinterfaces = Collections.unmodifiableList(superinterfaces);
superinterfacesRef = new SoftReference<List<InterfaceType>>(superinterfaces);
}
return superinterfaces;
}
public List<InterfaceType> subinterfaces() {
List<InterfaceType> subs = new ArrayList<InterfaceType>();
for (ReferenceType refType : vm.allClasses()) {
if (refType instanceof InterfaceType) {
InterfaceType interfaze = (InterfaceType)refType;
if (interfaze.isPrepared() && interfaze.superinterfaces().contains(this)) {
subs.add(interfaze);
}
}
}
return subs;
}
public List<ClassType> implementors() {
List<ClassType> implementors = new ArrayList<ClassType>();
for (ReferenceType refType : vm.allClasses()) {
if (refType instanceof ClassType) {
ClassType clazz = (ClassType)refType;
if (clazz.isPrepared() && clazz.interfaces().contains(this)) {
implementors.add(clazz);
}
}
}
return implementors;
}
public boolean isInitialized() {
return isPrepared();
}
public String toString() {
return "interface " + name() + " (" + loaderString() + ")";
}
@Override
InvocationResult waitForReply(PacketStream stream) throws JDWPException {
return new IResult(JDWP.InterfaceType.InvokeMethod.waitForReply(vm, stream));
}
@Override
CommandSender getInvokeMethodSender(final ThreadReferenceImpl thread,
final MethodImpl method,
final ValueImpl[] args,
final int options) {
return () ->
JDWP.InterfaceType.InvokeMethod.enqueueCommand(vm,
InterfaceTypeImpl.this,
thread,
method.ref(),
args,
options);
}
@Override
ClassType superclass() {
return null;
}
@Override
boolean isAssignableTo(ReferenceType type) {
if (type.name().equals("java.lang.Object")) {
// interfaces are always assignable to j.l.Object
return true;
}
return super.isAssignableTo(type);
}
@Override
List<InterfaceType> interfaces() {
return superinterfaces();
}
@Override
boolean canInvoke(Method method) {
// method must be directly in this interface
return this.equals(method.declaringType());
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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 com.sun.jdi.event.*;
import java.util.*;
public class InternalEventHandler implements Runnable
{
EventQueueImpl queue;
VirtualMachineImpl vm;
InternalEventHandler(VirtualMachineImpl vm, EventQueueImpl queue)
{
this.vm = vm;
this.queue = queue;
Thread thread = new Thread(vm.threadGroupForJDI(), this,
"JDI Internal Event Handler");
thread.setDaemon(true);
thread.start();
}
public void run() {
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
vm.printTrace("Internal event handler running");
}
try {
while (true) {
try {
EventSet eventSet = queue.removeInternal();
EventIterator it = eventSet.eventIterator();
while (it.hasNext()) {
Event event = it.nextEvent();
if (event instanceof ClassUnloadEvent) {
ClassUnloadEvent cuEvent = (ClassUnloadEvent)event;
vm.removeReferenceType(cuEvent.classSignature());
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
vm.printTrace("Handled Unload Event for " +
cuEvent.classSignature());
}
} else if (event instanceof ClassPrepareEvent) {
ClassPrepareEvent cpEvent = (ClassPrepareEvent)event;
((ReferenceTypeImpl)cpEvent.referenceType())
.markPrepared();
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
vm.printTrace("Handled Prepare Event for " +
cpEvent.referenceType().name());
}
}
}
/*
* Handle exceptions that can occur in normal operation
* but which can't be accounted for by event builder
* methods. The thread should not be terminated if they
* occur.
*
* TO DO: We need a better way to log these conditions.
*/
} catch (VMOutOfMemoryException vmme) {
vmme.printStackTrace();
} catch (InconsistentDebugInfoException idie) {
idie.printStackTrace();
/*
* If any of these exceptions below occurs, there is some
* sort of programming error that should be addressed in
* the JDI implemementation. However, it would cripple
* the implementation if we let this thread die due to
* one of them. So, a notification of the exception is
* given and we attempt to continue.
*/
} catch (ObjectCollectedException oce) {
oce.printStackTrace();
} catch (ClassNotPreparedException cnpe) {
cnpe.printStackTrace();
}
}
} catch (InterruptedException e) { // should we really die here
} catch (VMDisconnectedException e) { // time to die
}
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
vm.printTrace("Internal event handler exiting");
}
}
}

View File

@@ -0,0 +1,306 @@
/*
* Copyright (c) 2014, 2018, 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.ClassNotLoadedException;
import com.sun.jdi.ClassType;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.InterfaceType;
import com.sun.jdi.InvalidTypeException;
import com.sun.jdi.InvocationException;
import com.sun.jdi.Method;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.Value;
import com.sun.jdi.VirtualMachine;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* A supertype for ReferenceTypes allowing method invocations
*/
abstract class InvokableTypeImpl extends ReferenceTypeImpl {
/**
* The invocation result wrapper
* It is necessary because both ClassType and InterfaceType
* use their own type to represent the invocation result
*/
static interface InvocationResult {
ObjectReferenceImpl getException();
ValueImpl getResult();
}
InvokableTypeImpl(VirtualMachine aVm, long aRef) {
super(aVm, aRef);
}
/**
* Method invocation support.
* Shared by ClassType and InterfaceType
* @param threadIntf the thread in which to invoke.
* @param methodIntf method the {@link Method} to invoke.
* @param origArguments the list of {@link Value} arguments bound to the
* invoked method. Values from the list are assigned to arguments
* in the order they appear in the method signature.
* @param options the integer bit flag options.
* @return a {@link Value} mirror of the invoked method's return value.
* @throws java.lang.IllegalArgumentException if the method is not
* a member of this type, if the size of the argument list
* does not match the number of declared arguments for the method, or
* if the method is not static or is a static initializer.
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* type.
* @throws ClassNotLoadedException if any argument type has not yet been loaded
* through the appropriate class loader.
* @throws IncompatibleThreadStateException if the specified thread has not
* been suspended by an event.
* @throws InvocationException if the method invocation resulted in
* an exception in the target VM.
* @throws InvalidTypeException If the arguments do not meet this requirement --
* Object arguments must be assignment compatible with the argument
* type. This implies that the argument type must be
* loaded through the enclosing class's class loader.
* Primitive arguments must be either assignment compatible with the
* argument type or must be convertible to the argument type without loss
* of information. See JLS section 5.2 for more information on assignment
* compatibility.
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}.
*/
final public Value invokeMethod(ThreadReference threadIntf, Method methodIntf,
List<? extends Value> origArguments, int options)
throws InvalidTypeException,
ClassNotLoadedException,
IncompatibleThreadStateException,
InvocationException {
validateMirror(threadIntf);
validateMirror(methodIntf);
validateMirrorsOrNulls(origArguments);
MethodImpl method = (MethodImpl) methodIntf;
ThreadReferenceImpl thread = (ThreadReferenceImpl) threadIntf;
validateMethodInvocation(method);
List<? extends Value> arguments = method.validateAndPrepareArgumentsForInvoke(origArguments);
ValueImpl[] args = arguments.toArray(new ValueImpl[0]);
InvocationResult ret;
try {
PacketStream stream = sendInvokeCommand(thread, method, args, options);
ret = waitForReply(stream);
} catch (JDWPException exc) {
if (exc.errorCode() == JDWP.Error.INVALID_THREAD) {
throw new IncompatibleThreadStateException();
} else {
throw exc.toJDIException();
}
}
/*
* There is an implict VM-wide suspend at the conclusion
* of a normal (non-single-threaded) method invoke
*/
if ((options & ClassType.INVOKE_SINGLE_THREADED) == 0) {
vm.notifySuspend();
}
if (ret.getException() != null) {
throw new InvocationException(ret.getException());
} else {
return ret.getResult();
}
}
@Override
boolean isAssignableTo(ReferenceType type) {
ClassTypeImpl superclazz = (ClassTypeImpl) superclass();
if (this.equals(type)) {
return true;
} else if ((superclazz != null) && superclazz.isAssignableTo(type)) {
return true;
} else {
List<InterfaceType> interfaces = interfaces();
Iterator<InterfaceType> iter = interfaces.iterator();
while (iter.hasNext()) {
InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next();
if (interfaze.isAssignableTo(type)) {
return true;
}
}
return false;
}
}
@Override
final void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> seenInterfaces) {
/*
* Add methods from
* parent types first, so that the methods in this class will
* overwrite them in the hash table
*/
Iterator<InterfaceType> iter = interfaces().iterator();
while (iter.hasNext()) {
InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next();
if (!seenInterfaces.contains(interfaze)) {
interfaze.addVisibleMethods(methodMap, seenInterfaces);
seenInterfaces.add(interfaze);
}
}
ClassTypeImpl clazz = (ClassTypeImpl) superclass();
if (clazz != null) {
clazz.addVisibleMethods(methodMap, seenInterfaces);
}
addToMethodMap(methodMap, methods());
}
final void addInterfaces(List<InterfaceType> list) {
List<InterfaceType> immediate = interfaces();
list.addAll(interfaces());
Iterator<InterfaceType> iter = immediate.iterator();
while (iter.hasNext()) {
InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next();
interfaze.addInterfaces(list);
}
ClassTypeImpl superclass = (ClassTypeImpl) superclass();
if (superclass != null) {
superclass.addInterfaces(list);
}
}
/**
* Returns all the implemented interfaces recursively
* @return A list of all the implemented interfaces (recursively)
*/
final List<InterfaceType> getAllInterfaces() {
List<InterfaceType> all = new ArrayList<>();
addInterfaces(all);
return all;
}
/**
* Shared implementation of {@linkplain ClassType#allMethods()} and
* {@linkplain InterfaceType#allMethods()}
* @return A list of all methods (recursively)
*/
public final List<Method> allMethods() {
ArrayList<Method> list = new ArrayList<>(methods());
ClassType clazz = superclass();
while (clazz != null) {
list.addAll(clazz.methods());
clazz = clazz.superclass();
}
/*
* Avoid duplicate checking on each method by iterating through
* duplicate-free allInterfaces() rather than recursing
*/
for (InterfaceType interfaze : getAllInterfaces()) {
list.addAll(interfaze.methods());
}
return list;
}
@Override
final List<ReferenceType> inheritedTypes() {
List<ReferenceType> inherited = new ArrayList<>();
if (superclass() != null) {
inherited.add(0, superclass()); /* insert at front */
}
for (ReferenceType rt : interfaces()) {
inherited.add(rt);
}
return inherited;
}
private PacketStream sendInvokeCommand(final ThreadReferenceImpl thread,
final MethodImpl method,
final ValueImpl[] args,
final int options) {
CommandSender sender = getInvokeMethodSender(thread, method, args, options);
PacketStream stream;
if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0) {
stream = thread.sendResumingCommand(sender);
} else {
stream = vm.sendResumingCommand(sender);
}
return stream;
}
private void validateMethodInvocation(Method method)
throws InvalidTypeException,
InvocationException {
if (!canInvoke(method)) {
throw new IllegalArgumentException("Invalid method");
}
/*
* Method must be a static and not a static initializer
*/
if (!method.isStatic()) {
throw new IllegalArgumentException("Cannot invoke instance method on a class/interface type");
} else if (method.isStaticInitializer()) {
throw new IllegalArgumentException("Cannot invoke static initializer");
}
}
/**
* A subclass will provide specific {@linkplain CommandSender}
* @param thread the current invocation thread
* @param method the method to invoke
* @param args the arguments to pass to the method
* @param options the integer bit flag options
* @return the specific {@literal CommandSender} instance
*/
abstract CommandSender getInvokeMethodSender(ThreadReferenceImpl thread,
MethodImpl method,
ValueImpl[] args,
int options);
/**
* Waits for the reply to the last sent command
* @param stream the stream to listen for the reply on
* @return the {@linkplain InvocationResult} instance
* @throws JDWPException when something goes wrong in JDWP
*/
abstract InvocationResult waitForReply(PacketStream stream) throws JDWPException;
/**
* Get the {@linkplain ReferenceType} superclass
* @return the superclass or null
*/
abstract ClassType superclass();
/**
* Get the implemented/extended interfaces
* @return the list of implemented/extended interfaces
*/
abstract List<InterfaceType> interfaces();
/**
* Checks the provided method whether it can be invoked
* @param method the method to check
* @return {@code TRUE} if the implementation knows how to invoke the method,
* {@code FALSE} otherwise
*/
abstract boolean canInvoke(Method method);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
/*
* 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.*;
class JDWPException extends Exception {
private static final long serialVersionUID = -6321344442751299874L;
short errorCode;
JDWPException(short errorCode) {
super();
this.errorCode = errorCode;
}
short errorCode() {
return errorCode;
}
RuntimeException toJDIException() {
switch (errorCode) {
case JDWP.Error.INVALID_OBJECT:
return new ObjectCollectedException();
case JDWP.Error.VM_DEAD:
return new VMDisconnectedException();
case JDWP.Error.OUT_OF_MEMORY:
return new VMOutOfMemoryException();
case JDWP.Error.CLASS_NOT_PREPARED:
return new ClassNotPreparedException();
case JDWP.Error.INVALID_FRAMEID:
case JDWP.Error.NOT_CURRENT_FRAME:
return new InvalidStackFrameException();
case JDWP.Error.NOT_IMPLEMENTED:
return new UnsupportedOperationException();
case JDWP.Error.INVALID_INDEX:
case JDWP.Error.INVALID_LENGTH:
return new IndexOutOfBoundsException();
case JDWP.Error.TYPE_MISMATCH:
return new InconsistentDebugInfoException();
case JDWP.Error.INVALID_THREAD:
return new IllegalThreadStateException();
default:
return new InternalException("Unexpected JDWP Error: " + errorCode, errorCode);
}
}
}

View File

@@ -0,0 +1,241 @@
/*
* Copyright (c) 1998, 2008, 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 java.util.List;
import java.util.ArrayList;
public class JNITypeParser {
static final char SIGNATURE_ENDCLASS = ';';
static final char SIGNATURE_FUNC = '(';
static final char SIGNATURE_ENDFUNC = ')';
private String signature;
private List<String> typeNameList;
private List<String> signatureList;
private int currentIndex;
JNITypeParser(String signature) {
this.signature = signature;
}
static String typeNameToSignature(String signature) {
StringBuffer buffer = new StringBuffer();
int firstIndex = signature.indexOf('[');
int index = firstIndex;
while (index != -1) {
buffer.append('[');
index = signature.indexOf('[', index + 1);
}
if (firstIndex != -1) {
signature = signature.substring(0, firstIndex);
}
if (signature.equals("boolean")) {
buffer.append('Z');
} else if (signature.equals("byte")) {
buffer.append('B');
} else if (signature.equals("char")) {
buffer.append('C');
} else if (signature.equals("short")) {
buffer.append('S');
} else if (signature.equals("int")) {
buffer.append('I');
} else if (signature.equals("long")) {
buffer.append('J');
} else if (signature.equals("float")) {
buffer.append('F');
} else if (signature.equals("double")) {
buffer.append('D');
} else {
buffer.append('L');
buffer.append(signature.replace('.', '/'));
buffer.append(';');
}
return buffer.toString();
}
String typeName() {
return typeNameList().get(typeNameList().size()-1);
}
List<String> argumentTypeNames() {
return typeNameList().subList(0, typeNameList().size() - 1);
}
String signature() {
return signatureList().get(signatureList().size()-1);
}
List<String> argumentSignatures() {
return signatureList().subList(0, signatureList().size() - 1);
}
int dimensionCount() {
int count = 0;
String signature = signature();
while (signature.charAt(count) == '[') {
count++;
}
return count;
}
String componentSignature(int level) {
return signature().substring(level);
}
private synchronized List<String> signatureList() {
if (signatureList == null) {
signatureList = new ArrayList<String>(10);
String elem;
currentIndex = 0;
while(currentIndex < signature.length()) {
elem = nextSignature();
signatureList.add(elem);
}
if (signatureList.size() == 0) {
throw new IllegalArgumentException("Invalid JNI signature '" +
signature + "'");
}
}
return signatureList;
}
private synchronized List<String> typeNameList() {
if (typeNameList == null) {
typeNameList = new ArrayList<String>(10);
String elem;
currentIndex = 0;
while(currentIndex < signature.length()) {
elem = nextTypeName();
typeNameList.add(elem);
}
if (typeNameList.size() == 0) {
throw new IllegalArgumentException("Invalid JNI signature '" +
signature + "'");
}
}
return typeNameList;
}
private String nextSignature() {
char key = signature.charAt(currentIndex++);
switch(key) {
case (JDWP.Tag.ARRAY):
return key + nextSignature();
case (JDWP.Tag.OBJECT):
int endClass = signature.indexOf(SIGNATURE_ENDCLASS,
currentIndex);
String retVal = signature.substring(currentIndex - 1,
endClass + 1);
currentIndex = endClass + 1;
return retVal;
case (JDWP.Tag.VOID):
case (JDWP.Tag.BOOLEAN):
case (JDWP.Tag.BYTE):
case (JDWP.Tag.CHAR):
case (JDWP.Tag.SHORT):
case (JDWP.Tag.INT):
case (JDWP.Tag.LONG):
case (JDWP.Tag.FLOAT):
case (JDWP.Tag.DOUBLE):
return String.valueOf(key);
case SIGNATURE_ENDFUNC:
case SIGNATURE_FUNC:
return nextSignature();
default:
throw new IllegalArgumentException(
"Invalid JNI signature character '" + key + "'");
}
}
private String nextTypeName() {
char key = signature.charAt(currentIndex++);
switch(key) {
case (JDWP.Tag.ARRAY):
return nextTypeName() + "[]";
case (JDWP.Tag.BYTE):
return "byte";
case (JDWP.Tag.CHAR):
return "char";
case (JDWP.Tag.OBJECT):
int endClass = signature.indexOf(SIGNATURE_ENDCLASS,
currentIndex);
String retVal = signature.substring(currentIndex,
endClass);
retVal = retVal.replace('/','.');
currentIndex = endClass + 1;
return retVal;
case (JDWP.Tag.FLOAT):
return "float";
case (JDWP.Tag.DOUBLE):
return "double";
case (JDWP.Tag.INT):
return "int";
case (JDWP.Tag.LONG):
return "long";
case (JDWP.Tag.SHORT):
return "short";
case (JDWP.Tag.VOID):
return "void";
case (JDWP.Tag.BOOLEAN):
return "boolean";
case SIGNATURE_ENDFUNC:
case SIGNATURE_FUNC:
return nextTypeName();
default:
throw new IllegalArgumentException(
"Invalid JNI signature character '" + key + "'");
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 2001, 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.*;
interface LineInfo {
String liStratum();
int liLineNumber();
String liSourceName() throws AbsentInformationException;
String liSourcePath() throws AbsentInformationException;
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 1998, 2004, 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.*;
public class LocalVariableImpl extends MirrorImpl
implements LocalVariable, ValueContainer
{
private final Method method;
private final int slot;
private final Location scopeStart;
private final Location scopeEnd;
private final String name;
private final String signature;
private String genericSignature = null;
LocalVariableImpl(VirtualMachine vm, Method method,
int slot, Location scopeStart, Location scopeEnd,
String name, String signature,
String genericSignature) {
super(vm);
this.method = method;
this.slot = slot;
this.scopeStart = scopeStart;
this.scopeEnd = scopeEnd;
this.name = name;
this.signature = signature;
if (genericSignature != null && genericSignature.length() > 0) {
this.genericSignature = genericSignature;
} else {
// The Spec says to return null for non-generic types
this.genericSignature = null;
}
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof LocalVariableImpl)) {
LocalVariableImpl other = (LocalVariableImpl)obj;
return ((slot() == other.slot()) &&
(scopeStart != null) &&
(scopeStart.equals(other.scopeStart)) &&
(super.equals(obj)));
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return ((scopeStart.hashCode() << 4) + slot());
}
public int compareTo(LocalVariable object) {
LocalVariableImpl other = (LocalVariableImpl)object;
int rc = scopeStart.compareTo(other.scopeStart);
if (rc == 0) {
rc = slot() - other.slot();
}
return rc;
}
public String name() {
return name;
}
/**
* @return a text representation of the declared type
* of this variable.
*/
public String typeName() {
JNITypeParser parser = new JNITypeParser(signature);
return parser.typeName();
}
public Type type() throws ClassNotLoadedException {
return findType(signature());
}
public Type findType(String signature) throws ClassNotLoadedException {
ReferenceTypeImpl enclosing = (ReferenceTypeImpl)method.declaringType();
return enclosing.findType(signature);
}
public String signature() {
return signature;
}
public String genericSignature() {
return genericSignature;
}
public boolean isVisible(StackFrame frame) {
validateMirror(frame);
Method frameMethod = frame.location().method();
if (!frameMethod.equals(method)) {
throw new IllegalArgumentException(
"frame method different than variable's method");
}
// this is here to cover the possibility that we will
// allow LocalVariables for native methods. If we do
// so we will have to re-examinine this.
if (frameMethod.isNative()) {
return false;
}
return ((scopeStart.compareTo(frame.location()) <= 0)
&& (scopeEnd.compareTo(frame.location()) >= 0));
}
public boolean isArgument() {
try {
MethodImpl method = (MethodImpl)scopeStart.method();
return (slot < method.argSlotCount());
} catch (AbsentInformationException e) {
// If this variable object exists, there shouldn't be absent info
throw new InternalException();
}
}
int slot() {
return slot;
}
/*
* Compilers/VMs can have byte code ranges for variables of the
* same names that overlap. This is because the byte code ranges
* aren't necessarily scopes; they may have more to do with the
* lifetime of the variable's slot, depending on implementation.
*
* This method determines whether this variable hides an
* identically named variable; ie, their byte code ranges overlap
* this one starts after the given one. If it returns true this
* variable should be preferred when looking for a single variable
* with its name when both variables are visible.
*/
boolean hides(LocalVariable other) {
LocalVariableImpl otherImpl = (LocalVariableImpl)other;
if (!method.equals(otherImpl.method) ||
!name.equals(otherImpl.name)) {
return false;
} else {
return (scopeStart.compareTo(otherImpl.scopeStart) > 0);
}
}
public String toString() {
return name() + " in " + method.toString() +
"@" + scopeStart.toString();
}
}

View File

@@ -0,0 +1,227 @@
/*
* Copyright (c) 1998, 2004, 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.*;
public class LocationImpl extends MirrorImpl implements Location {
private final ReferenceTypeImpl declaringType;
private Method method;
private long methodRef;
private long codeIndex;
private LineInfo baseLineInfo = null;
private LineInfo otherLineInfo = null;
LocationImpl(VirtualMachine vm,
Method method, long codeIndex) {
super(vm);
this.method = method;
this.codeIndex = method.isNative()? -1 : codeIndex;
this.declaringType = (ReferenceTypeImpl)method.declaringType();
}
/*
* This constructor allows lazy creation of the method mirror. This
* can be a performance savings if the method mirror does not yet
* exist.
*/
LocationImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
long methodRef, long codeIndex) {
super(vm);
this.method = null;
this.codeIndex = codeIndex;
this.declaringType = declaringType;
this.methodRef = methodRef;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof Location)) {
Location other = (Location)obj;
return (method().equals(other.method())) &&
(codeIndex() == other.codeIndex()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: better hash code?
*/
return method().hashCode() + (int)codeIndex();
}
public int compareTo(Location object) {
LocationImpl other = (LocationImpl)object;
int rc = method().compareTo(other.method());
if (rc == 0) {
long diff = codeIndex() - other.codeIndex();
if (diff < 0)
return -1;
else if (diff > 0)
return 1;
else
return 0;
}
return rc;
}
public ReferenceType declaringType() {
return declaringType;
}
public Method method() {
if (method == null) {
method = declaringType.getMethodMirror(methodRef);
if (method.isNative()) {
codeIndex = -1;
}
}
return method;
}
public long codeIndex() {
method(); // be sure information is up-to-date
return codeIndex;
}
LineInfo getBaseLineInfo(SDE.Stratum stratum) {
LineInfo lineInfo;
/* check if there is cached info to use */
if (baseLineInfo != null) {
return baseLineInfo;
}
/* compute the line info */
MethodImpl methodImpl = (MethodImpl)method();
lineInfo = methodImpl.codeIndexToLineInfo(stratum,
codeIndex());
/* cache it */
addBaseLineInfo(lineInfo);
return lineInfo;
}
LineInfo getLineInfo(SDE.Stratum stratum) {
LineInfo lineInfo;
/* base stratum is done slighly differently */
if (stratum.isJava()) {
return getBaseLineInfo(stratum);
}
/* check if there is cached info to use */
lineInfo = otherLineInfo; // copy because of concurrency
if (lineInfo != null &&
stratum.id().equals(lineInfo.liStratum())) {
return lineInfo;
}
int baseLineNumber = lineNumber(SDE.BASE_STRATUM_NAME);
SDE.LineStratum lineStratum =
stratum.lineStratum(declaringType, baseLineNumber);
if (lineStratum != null && lineStratum.lineNumber() != -1) {
lineInfo = new StratumLineInfo(stratum.id(),
lineStratum.lineNumber(),
lineStratum.sourceName(),
lineStratum.sourcePath());
} else {
/* find best match */
MethodImpl methodImpl = (MethodImpl)method();
lineInfo = methodImpl.codeIndexToLineInfo(stratum,
codeIndex());
}
/* cache it */
addStratumLineInfo(lineInfo);
return lineInfo;
}
void addStratumLineInfo(LineInfo lineInfo) {
otherLineInfo = lineInfo;
}
void addBaseLineInfo(LineInfo lineInfo) {
baseLineInfo = lineInfo;
}
public String sourceName() throws AbsentInformationException {
return sourceName(vm.getDefaultStratum());
}
public String sourceName(String stratumID)
throws AbsentInformationException {
return sourceName(declaringType.stratum(stratumID));
}
String sourceName(SDE.Stratum stratum)
throws AbsentInformationException {
return getLineInfo(stratum).liSourceName();
}
public String sourcePath() throws AbsentInformationException {
return sourcePath(vm.getDefaultStratum());
}
public String sourcePath(String stratumID)
throws AbsentInformationException {
return sourcePath(declaringType.stratum(stratumID));
}
String sourcePath(SDE.Stratum stratum)
throws AbsentInformationException {
return getLineInfo(stratum).liSourcePath();
}
public int lineNumber() {
return lineNumber(vm.getDefaultStratum());
}
public int lineNumber(String stratumID) {
return lineNumber(declaringType.stratum(stratumID));
}
int lineNumber(SDE.Stratum stratum) {
return getLineInfo(stratum).liLineNumber();
}
public String toString() {
if (lineNumber() == -1) {
return method().toString() + "+" + codeIndex();
} else {
return declaringType().name() + ":" + lineNumber();
}
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1998, 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.*;
/**
* This class is used by the back end to do thread synchronization.
* We don't want to use java.lang.Object(s) for two reasons: we can't
* filter them out, and this class should use less heap.
*/
public class LockObject
{
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class LongTypeImpl extends PrimitiveTypeImpl implements LongType {
LongTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.LONG);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedLongValue());
}
}

View File

@@ -0,0 +1,146 @@
/*
* 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.*;
public class LongValueImpl extends PrimitiveValueImpl
implements LongValue {
private long value;
LongValueImpl(VirtualMachine aVm,long aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof LongValue)) {
return (value == ((LongValue)obj).value()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public int compareTo(LongValue obj) {
long other = obj.value();
if (value() < other) {
return -1;
} else if (value() == other) {
return 0;
} else {
return 1;
}
}
public Type type() {
return vm.theLongType();
}
public long value() {
return value;
}
public boolean booleanValue() {
return(value == 0)?false:true;
}
public byte byteValue() {
return(byte)value;
}
public char charValue() {
return(char)value;
}
public short shortValue() {
return(short)value;
}
public int intValue() {
return(int)value;
}
public long longValue() {
return value;
}
public float floatValue() {
return(float)value;
}
public double doubleValue() {
return(double)value;
}
byte checkedByteValue() throws InvalidTypeException {
if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to byte");
} else {
return super.checkedByteValue();
}
}
char checkedCharValue() throws InvalidTypeException {
if ((value > Character.MAX_VALUE) || (value < Character.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to char");
} else {
return super.checkedCharValue();
}
}
short checkedShortValue() throws InvalidTypeException {
if ((value > Short.MAX_VALUE) || (value < Short.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to short");
} else {
return super.checkedShortValue();
}
}
int checkedIntValue() throws InvalidTypeException {
if ((value > Integer.MAX_VALUE) || (value < Integer.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to int");
} else {
return super.checkedIntValue();
}
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.LONG;
}
}

View File

@@ -0,0 +1,410 @@
/*
* Copyright (c) 1998, 2016, 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.Iterator;
import java.util.ArrayList;
import java.util.Comparator;
public abstract class MethodImpl extends TypeComponentImpl
implements Method {
private JNITypeParser signatureParser;
abstract int argSlotCount() throws AbsentInformationException;
abstract List<Location> allLineLocations(SDE.Stratum stratum,
String sourceName)
throws AbsentInformationException;
abstract List<Location> locationsOfLine(SDE.Stratum stratum,
String sourceName,
int lineNumber)
throws AbsentInformationException;
MethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
long ref,
String name, String signature,
String genericSignature, int modifiers) {
super(vm, declaringType, ref, name, signature,
genericSignature, modifiers);
signatureParser = new JNITypeParser(signature);
}
static MethodImpl createMethodImpl(VirtualMachine vm,
ReferenceTypeImpl declaringType,
long ref,
String name,
String signature,
String genericSignature,
int modifiers) {
if ((modifiers &
(VMModifiers.NATIVE | VMModifiers.ABSTRACT)) != 0) {
return new NonConcreteMethodImpl(vm, declaringType, ref,
name, signature,
genericSignature,
modifiers);
} else {
return new ConcreteMethodImpl(vm, declaringType, ref,
name, signature,
genericSignature,
modifiers);
}
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof MethodImpl)) {
MethodImpl other = (MethodImpl)obj;
return (declaringType().equals(other.declaringType())) &&
(ref() == other.ref()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
return (int)ref();
}
public final List<Location> allLineLocations()
throws AbsentInformationException {
return allLineLocations(vm.getDefaultStratum(), null);
}
public List<Location> allLineLocations(String stratumID,
String sourceName)
throws AbsentInformationException {
return allLineLocations(declaringType.stratum(stratumID),
sourceName);
}
public final List<Location> locationsOfLine(int lineNumber)
throws AbsentInformationException {
return locationsOfLine(vm.getDefaultStratum(),
null, lineNumber);
}
public List<Location> locationsOfLine(String stratumID,
String sourceName,
int lineNumber)
throws AbsentInformationException {
return locationsOfLine(declaringType.stratum(stratumID),
sourceName, lineNumber);
}
LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
long codeIndex) {
if (stratum.isJava()) {
return new BaseLineInfo(-1, declaringType);
} else {
return new StratumLineInfo(stratum.id(), -1,
null, null);
}
}
/**
* @return a text representation of the declared return type
* of this method.
*/
public String returnTypeName() {
return signatureParser.typeName();
}
private String returnSignature() {
return signatureParser.signature();
}
public Type returnType() throws ClassNotLoadedException {
return findType(returnSignature());
}
public Type findType(String signature) throws ClassNotLoadedException {
ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
return enclosing.findType(signature);
}
public List<String> argumentTypeNames() {
return signatureParser.argumentTypeNames();
}
public List<String> argumentSignatures() {
return signatureParser.argumentSignatures();
}
Type argumentType(int index) throws ClassNotLoadedException {
ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
String signature = argumentSignatures().get(index);
return enclosing.findType(signature);
}
public List<Type> argumentTypes() throws ClassNotLoadedException {
int size = argumentSignatures().size();
ArrayList<Type> types = new ArrayList<Type>(size);
for (int i = 0; i < size; i++) {
Type type = argumentType(i);
types.add(type);
}
return types;
}
public int compareTo(Method method) {
ReferenceTypeImpl declaringType = (ReferenceTypeImpl)declaringType();
int rc = declaringType.compareTo(method.declaringType());
if (rc == 0) {
rc = declaringType.indexOf(this) -
declaringType.indexOf(method);
}
return rc;
}
public boolean isAbstract() {
return isModifierSet(VMModifiers.ABSTRACT);
}
public boolean isDefault() {
return !isModifierSet(VMModifiers.ABSTRACT) &&
!isModifierSet(VMModifiers.STATIC) &&
!isModifierSet(VMModifiers.PRIVATE) &&
declaringType() instanceof InterfaceType;
}
public boolean isSynchronized() {
return isModifierSet(VMModifiers.SYNCHRONIZED);
}
public boolean isNative() {
return isModifierSet(VMModifiers.NATIVE);
}
public boolean isVarArgs() {
return isModifierSet(VMModifiers.VARARGS);
}
public boolean isBridge() {
return isModifierSet(VMModifiers.BRIDGE);
}
public boolean isConstructor() {
return name().equals("<init>");
}
public boolean isStaticInitializer() {
return name().equals("<clinit>");
}
public boolean isObsolete() {
try {
return JDWP.Method.IsObsolete.process(vm,
declaringType, ref).isObsolete;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
/*
* A container class for the return value to allow
* proper type-checking.
*/
class ReturnContainer implements ValueContainer {
ReturnContainer() {
}
public Type type() throws ClassNotLoadedException {
return returnType();
}
public String typeName(){
return returnTypeName();
}
public String signature() {
return returnSignature(); //type().signature();
}
public Type findType(String signature) throws ClassNotLoadedException {
return MethodImpl.this.findType(signature);
}
}
ReturnContainer retValContainer = null;
ReturnContainer getReturnValueContainer() {
if (retValContainer == null) {
retValContainer = new ReturnContainer();
}
return retValContainer;
}
/*
* A container class for the argument to allow
* proper type-checking.
*/
class ArgumentContainer implements ValueContainer {
int index;
ArgumentContainer(int index) {
this.index = index;
}
public Type type() throws ClassNotLoadedException {
return argumentType(index);
}
public String typeName(){
return argumentTypeNames().get(index);
}
public String signature() {
return argumentSignatures().get(index);
}
public Type findType(String signature) throws ClassNotLoadedException {
return MethodImpl.this.findType(signature);
}
}
/*
* This is a var args method. Thus, its last param is an
* array. If the method has n params, then:
* 1. If there are n args and the last is the same type as the type of
* the last param, do nothing. IE, a String[]
* can be passed to a String...
* 2. If there are >= n arguments and for each arg whose number is >= n,
* the arg type is 'compatible' with the component type of
* the last param, then do
* - create an array of the type of the last param
* - put the n, ... args into this array.
* We might have to do conversions here.
* - put this array into arguments(n)
* - delete arguments(n+1), ...
* NOTE that this might modify the input list.
*/
void handleVarArgs(List<Value> arguments)
throws ClassNotLoadedException, InvalidTypeException {
List<Type> paramTypes = this.argumentTypes();
ArrayType lastParamType = (ArrayType)paramTypes.get(paramTypes.size() - 1);
Type componentType = lastParamType.componentType();
int argCount = arguments.size();
int paramCount = paramTypes.size();
if (argCount < paramCount - 1) {
// Error; will be caught later.
return;
}
if (argCount == paramCount - 1) {
// It is ok to pass 0 args to the var arg.
// We have to gen a 0 length array.
ArrayReference argArray = lastParamType.newInstance(0);
arguments.add(argArray);
return;
}
Value nthArgValue = arguments.get(paramCount - 1);
if (nthArgValue == null && argCount == paramCount) {
// We have one varargs parameter and it is null
// so we don't have to do anything.
return;
}
// If the first varargs parameter is null, then don't
// access its type since it can't be an array.
Type nthArgType = (nthArgValue == null) ? null : nthArgValue.type();
if (nthArgType instanceof ArrayTypeImpl) {
if (argCount == paramCount &&
((ArrayTypeImpl)nthArgType).isAssignableTo(lastParamType)) {
/*
* This is case 1. A compatible array is being passed to the
* var args array param. We don't have to do anything.
*/
return;
}
}
/*
* Case 2. We have to verify that the n, n+1, ... args are compatible
* with componentType, and do conversions if necessary and create
* an array of componentType to hold these possibly converted values.
*/
int count = argCount - paramCount + 1;
ArrayReference argArray = lastParamType.newInstance(count);
/*
* This will copy arguments(paramCount - 1) ... to argArray(0) ...
* doing whatever conversions are needed! It will throw an
* exception if an incompatible arg is encountered
*/
argArray.setValues(0, arguments, paramCount - 1, count);
arguments.set(paramCount - 1, argArray);
/*
* Remove the excess args
*/
for (int ii = paramCount; ii < argCount; ii++) {
arguments.remove(paramCount);
}
return;
}
/*
* The output list will be different than the input list.
*/
List<Value> validateAndPrepareArgumentsForInvoke(List<? extends Value> origArguments)
throws ClassNotLoadedException, InvalidTypeException {
List<Value> arguments = new ArrayList<Value>(origArguments);
if (isVarArgs()) {
handleVarArgs(arguments);
}
int argSize = arguments.size();
JNITypeParser parser = new JNITypeParser(signature());
List<String> signatures = parser.argumentSignatures();
if (signatures.size() != argSize) {
throw new IllegalArgumentException("Invalid argument count: expected " +
signatures.size() + ", received " +
arguments.size());
}
for (int i = 0; i < argSize; i++) {
Value value = arguments.get(i);
value = ValueImpl.prepareForAssignment(value,
new ArgumentContainer(i));
arguments.set(i, value);
}
return arguments;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(declaringType().name());
sb.append(".");
sb.append(name());
sb.append("(");
boolean first = true;
for (String name : argumentTypeNames()) {
if (!first) {
sb.append(", ");
}
sb.append(name);
first = false;
}
sb.append(")");
return sb.toString();
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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.Collection;
import java.util.Iterator;
abstract class MirrorImpl extends Object implements Mirror {
protected VirtualMachineImpl vm;
MirrorImpl(VirtualMachine aVm) {
super();
// Yes, its a bit of a hack. But by doing it this
// way, this is the only place we have to change
// typing to substitute a new impl.
vm = (VirtualMachineImpl)aVm;
}
public VirtualMachine virtualMachine() {
return vm;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof Mirror)) {
Mirror other = (Mirror)obj;
return vm.equals(other.virtualMachine());
} else {
return false;
}
}
public int hashCode() {
return vm.hashCode();
}
/**
* Throw NullPointerException on null mirror.
* Throw VMMismatchException on wrong VM.
*/
void validateMirror(Mirror mirror) {
if (!vm.equals(mirror.virtualMachine())) {
throw new VMMismatchException(mirror.toString());
}
}
/**
* Allow null mirror.
* Throw VMMismatchException on wrong VM.
*/
void validateMirrorOrNull(Mirror mirror) {
if ((mirror != null) && !vm.equals(mirror.virtualMachine())) {
throw new VMMismatchException(mirror.toString());
}
}
/**
* Throw NullPointerException on null mirrors.
* Throw VMMismatchException on wrong VM.
*/
void validateMirrors(Collection<? extends Mirror> mirrors) {
Iterator<? extends Mirror> iter = mirrors.iterator();
while (iter.hasNext()) {
MirrorImpl mirror = (MirrorImpl)iter.next();
if (!vm.equals(mirror.vm)) {
throw new VMMismatchException(mirror.toString());
}
}
}
/**
* Allow null mirrors.
* Throw VMMismatchException on wrong VM.
*/
void validateMirrorsOrNulls(Collection<? extends Mirror> mirrors) {
Iterator<? extends Mirror> iter = mirrors.iterator();
while (iter.hasNext()) {
MirrorImpl mirror = (MirrorImpl)iter.next();
if ((mirror != null) && !vm.equals(mirror.vm)) {
throw new VMMismatchException(mirror.toString());
}
}
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2005, 2008, 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.*;
public class MonitorInfoImpl extends MirrorImpl
implements MonitorInfo, ThreadListener {
/* Once false, monitorInfo should not be used.
* access synchronized on (vm.state())
*/
private boolean isValid = true;
ObjectReference monitor;
ThreadReference thread;
int stack_depth;
MonitorInfoImpl(VirtualMachine vm, ObjectReference mon,
ThreadReferenceImpl thread, int dpth) {
super(vm);
this.monitor = mon;
this.thread = thread;
this.stack_depth = dpth;
thread.addListener(this);
}
/*
* ThreadListener implementation
* Must be synchronized since we must protect against
* sending defunct (isValid == false) stack ids to the back-end.
*/
public boolean threadResumable(ThreadAction action) {
synchronized (vm.state()) {
if (isValid) {
isValid = false;
return false; /* remove this stack frame as a listener */
} else {
throw new InternalException(
"Invalid stack frame thread listener");
}
}
}
private void validateMonitorInfo() {
if (!isValid) {
throw new InvalidStackFrameException("Thread has been resumed");
}
}
public ObjectReference monitor() {
validateMonitorInfo();
return monitor;
}
public int stackDepth() {
validateMonitorInfo();
return stack_depth;
}
public ThreadReference thread() {
validateMonitorInfo();
return thread;
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 2000, 2003, 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.Map;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collections;
/**
* Represents non-concrete (that is, native or abstract) methods.
* Private to MethodImpl.
*/
public class NonConcreteMethodImpl extends MethodImpl {
private Location location = null;
NonConcreteMethodImpl(VirtualMachine vm,
ReferenceTypeImpl declaringType,
long ref,
String name, String signature,
String genericSignature, int modifiers) {
// The generic signature is set when this is created
super(vm, declaringType, ref, name, signature,
genericSignature, modifiers);
}
public Location location() {
if (isAbstract()) {
return null;
}
if (location == null) {
location = new LocationImpl(vm, this, -1);
}
return location;
}
public List<Location> allLineLocations(String stratumID,
String sourceName) {
return new ArrayList<Location>(0);
}
public List<Location> allLineLocations(SDE.Stratum stratum,
String sourceName) {
return new ArrayList<Location>(0);
}
public List<Location> locationsOfLine(String stratumID,
String sourceName,
int lineNumber) {
return new ArrayList<Location>(0);
}
public List<Location> locationsOfLine(SDE.Stratum stratum,
String sourceName,
int lineNumber) {
return new ArrayList<Location>(0);
}
public Location locationOfCodeIndex(long codeIndex) {
return null;
}
public List<LocalVariable> variables() throws AbsentInformationException {
throw new AbsentInformationException();
}
public List<LocalVariable> variablesByName(String name) throws AbsentInformationException {
throw new AbsentInformationException();
}
public List<LocalVariable> arguments() throws AbsentInformationException {
throw new AbsentInformationException();
}
public byte[] bytecodes() {
return new byte[0];
}
int argSlotCount() throws AbsentInformationException {
throw new InternalException("should not get here");
}
}

View File

@@ -0,0 +1,631 @@
/*
* Copyright (c) 1998, 2015, 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.*;
import java.util.ArrayList;
public class ObjectReferenceImpl extends ValueImpl
implements ObjectReference, VMListener {
protected long ref;
private ReferenceType type = null;
private int gcDisableCount = 0;
boolean addedListener = false;
// This is cached only while the VM is suspended
protected static class Cache {
JDWP.ObjectReference.MonitorInfo monitorInfo = null;
}
private static final Cache noInitCache = new Cache();
private static final Cache markerCache = new Cache();
private Cache cache = noInitCache;
private void disableCache() {
synchronized (vm.state()) {
cache = null;
}
}
private void enableCache() {
synchronized (vm.state()) {
cache = markerCache;
}
}
// Override in subclasses
protected Cache newCache() {
return new Cache();
}
protected Cache getCache() {
synchronized (vm.state()) {
if (cache == noInitCache) {
if (vm.state().isSuspended()) {
// Set cache now, otherwise newly created objects are
// not cached until resuspend
enableCache();
} else {
disableCache();
}
}
if (cache == markerCache) {
cache = newCache();
}
return cache;
}
}
// Return the ClassTypeImpl upon which to invoke a method.
// By default it is our very own referenceType() but subclasses
// can override.
protected ClassTypeImpl invokableReferenceType(Method method) {
return (ClassTypeImpl)referenceType();
}
ObjectReferenceImpl(VirtualMachine aVm,long aRef) {
super(aVm);
ref = aRef;
}
protected String description() {
return "ObjectReference " + uniqueID();
}
/*
* VMListener implementation
*/
public boolean vmSuspended(VMAction action) {
enableCache();
return true;
}
public boolean vmNotSuspended(VMAction action) {
// make sure that cache and listener management are synchronized
synchronized (vm.state()) {
if (cache != null && (vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace("Clearing temporary cache for " + description());
}
disableCache();
if (addedListener) {
/*
* If a listener was added (i.e. this is not a
* ObjectReference that adds a listener on startup),
* remove it here.
*/
addedListener = false;
return false; // false says remove
} else {
return true;
}
}
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof ObjectReferenceImpl)) {
ObjectReferenceImpl other = (ObjectReferenceImpl)obj;
return (ref() == other.ref()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
return(int)ref();
}
public Type type() {
return referenceType();
}
public ReferenceType referenceType() {
if (type == null) {
try {
JDWP.ObjectReference.ReferenceType rtinfo =
JDWP.ObjectReference.ReferenceType.process(vm, this);
type = vm.referenceType(rtinfo.typeID,
rtinfo.refTypeTag);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
return type;
}
public Value getValue(Field sig) {
List<Field> list = new ArrayList<Field>(1);
list.add(sig);
Map<Field, Value> map = getValues(list);
return map.get(sig);
}
public Map<Field,Value> getValues(List<? extends Field> theFields) {
validateMirrors(theFields);
List<Field> staticFields = new ArrayList<Field>(0);
int size = theFields.size();
List<Field> instanceFields = new ArrayList<Field>(size);
for (int i=0; i<size; i++) {
Field field = (Field)theFields.get(i);
// Make sure the field is valid
((ReferenceTypeImpl)referenceType()).validateFieldAccess(field);
// FIX ME! We need to do some sanity checking
// here; make sure the field belongs to this
// object.
if (field.isStatic())
staticFields.add(field);
else {
instanceFields.add(field);
}
}
Map<Field, Value> map;
if (staticFields.size() > 0) {
map = referenceType().getValues(staticFields);
} else {
map = new HashMap<Field, Value>(size);
}
size = instanceFields.size();
JDWP.ObjectReference.GetValues.Field[] queryFields =
new JDWP.ObjectReference.GetValues.Field[size];
for (int i=0; i<size; i++) {
FieldImpl field = (FieldImpl)instanceFields.get(i);/* thanks OTI */
queryFields[i] = new JDWP.ObjectReference.GetValues.Field(
field.ref());
}
ValueImpl[] values;
try {
values = JDWP.ObjectReference.GetValues.
process(vm, this, queryFields).values;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
if (size != values.length) {
throw new InternalException(
"Wrong number of values returned from target VM");
}
for (int i=0; i<size; i++) {
FieldImpl field = (FieldImpl)instanceFields.get(i);
map.put(field, values[i]);
}
return map;
}
public void setValue(Field field, Value value)
throws InvalidTypeException, ClassNotLoadedException {
validateMirror(field);
validateMirrorOrNull(value);
// Make sure the field is valid
((ReferenceTypeImpl)referenceType()).validateFieldSet(field);
if (field.isStatic()) {
ReferenceType type = referenceType();
if (type instanceof ClassType) {
((ClassType)type).setValue(field, value);
return;
} else {
throw new IllegalArgumentException(
"Invalid type for static field set");
}
}
try {
JDWP.ObjectReference.SetValues.FieldValue[] fvals =
new JDWP.ObjectReference.SetValues.FieldValue[1];
fvals[0] = new JDWP.ObjectReference.SetValues.FieldValue(
((FieldImpl)field).ref(),
// Validate and convert if necessary
ValueImpl.prepareForAssignment(value,
(FieldImpl)field));
try {
JDWP.ObjectReference.SetValues.process(vm, this, fvals);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
} catch (ClassNotLoadedException e) {
/*
* Since we got this exception,
* the field type must be a reference type. The value
* we're trying to set is null, but if the field's
* class has not yet been loaded through the enclosing
* class loader, then setting to null is essentially a
* no-op, and we should allow it without an exception.
*/
if (value != null) {
throw e;
}
}
}
void validateMethodInvocation(Method method, int options)
throws InvalidTypeException,
InvocationException {
/*
* Method must be in this object's class, a superclass, or
* implemented interface
*/
ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType();
if (!declType.isAssignableFrom(this)) {
throw new IllegalArgumentException("Invalid method");
}
if (declType instanceof ClassTypeImpl) {
validateClassMethodInvocation(method, options);
} else if (declType instanceof InterfaceTypeImpl) {
validateIfaceMethodInvocation(method, options);
} else {
throw new InvalidTypeException();
}
}
void validateClassMethodInvocation(Method method, int options)
throws InvalidTypeException,
InvocationException {
ClassTypeImpl clazz = invokableReferenceType(method);
/*
* Method must be a non-constructor
*/
if (method.isConstructor()) {
throw new IllegalArgumentException("Cannot invoke constructor");
}
/*
* For nonvirtual invokes, method must have a body
*/
if (isNonVirtual(options)) {
if (method.isAbstract()) {
throw new IllegalArgumentException("Abstract method");
}
}
/*
* Get the class containing the method that will be invoked.
* This class is needed only for proper validation of the
* method argument types.
*/
ClassTypeImpl invokedClass;
if (isNonVirtual(options)) {
// No overrides in non-virtual invokes
invokedClass = clazz;
} else {
/*
* For virtual invokes, find any override of the method.
* Since we are looking for a method with a real body, we
* don't need to bother with interfaces/abstract methods.
*/
Method invoker = clazz.concreteMethodByName(method.name(),
method.signature());
// invoker is supposed to be non-null under normal circumstances
invokedClass = (ClassTypeImpl)invoker.declaringType();
}
/* The above code is left over from previous versions.
* We haven't had time to divine the intent. jjh, 7/31/2003
*/
}
void validateIfaceMethodInvocation(Method method, int options)
throws InvalidTypeException,
InvocationException {
/*
* Only default methods allowed for nonvirtual invokes
*/
if (isNonVirtual(options) && !method.isDefault()) {
throw new IllegalArgumentException("Not a default method");
}
}
PacketStream sendInvokeCommand(final ThreadReferenceImpl thread,
final ClassTypeImpl refType,
final MethodImpl method,
final ValueImpl[] args,
final int options) {
CommandSender sender =
new CommandSender() {
public PacketStream send() {
return JDWP.ObjectReference.InvokeMethod.enqueueCommand(
vm, ObjectReferenceImpl.this,
thread, refType,
method.ref(), args, options);
}
};
PacketStream stream;
if ((options & INVOKE_SINGLE_THREADED) != 0) {
stream = thread.sendResumingCommand(sender);
} else {
stream = vm.sendResumingCommand(sender);
}
return stream;
}
public Value invokeMethod(ThreadReference threadIntf, Method methodIntf,
List<? extends Value> origArguments, int options)
throws InvalidTypeException,
IncompatibleThreadStateException,
InvocationException,
ClassNotLoadedException {
validateMirror(threadIntf);
validateMirror(methodIntf);
validateMirrorsOrNulls(origArguments);
MethodImpl method = (MethodImpl)methodIntf;
ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf;
if (method.isStatic()) {
if (referenceType() instanceof InterfaceType) {
InterfaceType type = (InterfaceType)referenceType();
return type.invokeMethod(thread, method, origArguments, options);
} else if (referenceType() instanceof ClassType) {
ClassType type = (ClassType)referenceType();
return type.invokeMethod(thread, method, origArguments, options);
} else {
throw new IllegalArgumentException("Invalid type for static method invocation");
}
}
validateMethodInvocation(method, options);
List<Value> arguments = method.validateAndPrepareArgumentsForInvoke(
origArguments);
ValueImpl[] args = arguments.toArray(new ValueImpl[0]);
JDWP.ObjectReference.InvokeMethod ret;
try {
PacketStream stream =
sendInvokeCommand(thread, invokableReferenceType(method),
method, args, options);
ret = JDWP.ObjectReference.InvokeMethod.waitForReply(vm, stream);
} catch (JDWPException exc) {
if (exc.errorCode() == JDWP.Error.INVALID_THREAD) {
throw new IncompatibleThreadStateException();
} else {
throw exc.toJDIException();
}
}
/*
* There is an implict VM-wide suspend at the conclusion
* of a normal (non-single-threaded) method invoke
*/
if ((options & INVOKE_SINGLE_THREADED) == 0) {
vm.notifySuspend();
}
if (ret.exception != null) {
throw new InvocationException(ret.exception);
} else {
return ret.returnValue;
}
}
/* leave synchronized to keep count accurate */
public synchronized void disableCollection() {
if (gcDisableCount == 0) {
try {
JDWP.ObjectReference.DisableCollection.process(vm, this);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
gcDisableCount++;
}
/* leave synchronized to keep count accurate */
public synchronized void enableCollection() {
gcDisableCount--;
if (gcDisableCount == 0) {
try {
JDWP.ObjectReference.EnableCollection.process(vm, this);
} catch (JDWPException exc) {
// If already collected, no harm done, no exception
if (exc.errorCode() != JDWP.Error.INVALID_OBJECT) {
throw exc.toJDIException();
}
return;
}
}
}
public boolean isCollected() {
try {
return JDWP.ObjectReference.IsCollected.process(vm, this).
isCollected;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
public long uniqueID() {
return ref();
}
JDWP.ObjectReference.MonitorInfo jdwpMonitorInfo()
throws IncompatibleThreadStateException {
JDWP.ObjectReference.MonitorInfo info = null;
try {
Cache local;
// getCache() and addlistener() must be synchronized
// so that no events are lost.
synchronized (vm.state()) {
local = getCache();
if (local != null) {
info = local.monitorInfo;
// Check if there will be something to cache
// and there is not already a listener
if (info == null && !vm.state().hasListener(this)) {
/* For other, less numerous objects, this is done
* in the constructor. Since there can be many
* ObjectReferences, the VM listener is installed
* and removed as needed.
* Listener must be installed before process()
*/
vm.state().addListener(this);
addedListener = true;
}
}
}
if (info == null) {
info = JDWP.ObjectReference.MonitorInfo.process(vm, this);
if (local != null) {
local.monitorInfo = info;
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace("ObjectReference " + uniqueID() +
" temporarily caching monitor info");
}
}
}
} catch (JDWPException exc) {
if (exc.errorCode() == JDWP.Error.THREAD_NOT_SUSPENDED) {
throw new IncompatibleThreadStateException();
} else {
throw exc.toJDIException();
}
}
return info;
}
public List<ThreadReference> waitingThreads() throws IncompatibleThreadStateException {
return Arrays.asList((ThreadReference[])jdwpMonitorInfo().waiters);
}
public ThreadReference owningThread() throws IncompatibleThreadStateException {
return jdwpMonitorInfo().owner;
}
public int entryCount() throws IncompatibleThreadStateException {
return jdwpMonitorInfo().entryCount;
}
public List<ObjectReference> referringObjects(long maxReferrers) {
if (!vm.canGetInstanceInfo()) {
throw new UnsupportedOperationException(
"target does not support getting referring objects");
}
if (maxReferrers < 0) {
throw new IllegalArgumentException("maxReferrers is less than zero: "
+ maxReferrers);
}
int intMax = (maxReferrers > Integer.MAX_VALUE)?
Integer.MAX_VALUE: (int)maxReferrers;
// JDWP can't currently handle more than this (in mustang)
try {
return Arrays.asList((ObjectReference[])JDWP.ObjectReference.ReferringObjects.
process(vm, this, intMax).referringObjects);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
long ref() {
return ref;
}
boolean isClassObject() {
/*
* Don't need to worry about subclasses since java.lang.Class is final.
*/
return referenceType().name().equals("java.lang.Class");
}
ValueImpl prepareForAssignmentTo(ValueContainer destination)
throws InvalidTypeException,
ClassNotLoadedException {
validateAssignment(destination);
return this; // conversion never necessary
}
void validateAssignment(ValueContainer destination)
throws InvalidTypeException, ClassNotLoadedException {
/*
* Do these simpler checks before attempting a query of the destination's
* type which might cause a confusing ClassNotLoadedException if
* the destination is primitive or an array.
*/
/*
* TO DO: Centralize JNI signature knowledge
*/
if (destination.signature().length() == 1) {
throw new InvalidTypeException("Can't assign object value to primitive");
}
if ((destination.signature().charAt(0) == '[') &&
(type().signature().charAt(0) != '[')) {
throw new InvalidTypeException("Can't assign non-array value to an array");
}
if ("void".equals(destination.typeName())) {
throw new InvalidTypeException("Can't assign object value to a void");
}
// Validate assignment
ReferenceType destType = (ReferenceTypeImpl)destination.type();
ReferenceTypeImpl myType = (ReferenceTypeImpl)referenceType();
if (!myType.isAssignableTo(destType)) {
JNITypeParser parser = new JNITypeParser(destType.signature());
String destTypeName = parser.typeName();
throw new InvalidTypeException("Can't assign " +
type().name() +
" to " + destTypeName);
}
}
public String toString() {
return "instance of " + referenceType().name() + "(id=" + uniqueID() + ")";
}
byte typeValueKey() {
return JDWP.Tag.OBJECT;
}
private static boolean isNonVirtual(int options) {
return (options & INVOKE_NONVIRTUAL) != 0;
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2000, 2003, 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;
/**
* Represents methods which have changed when the class was redefined.
*/
public class ObsoleteMethodImpl extends NonConcreteMethodImpl {
private Location location = null;
ObsoleteMethodImpl(VirtualMachine vm,
ReferenceTypeImpl declaringType) {
super(vm, declaringType, 0, "<obsolete>", "", null, 0);
}
public boolean isObsolete() {
return true;
}
public String returnTypeName() {
return "<unknown>";
}
public Type returnType() throws ClassNotLoadedException {
throw new ClassNotLoadedException("type unknown");
}
public List<String> argumentTypeNames() {
return new ArrayList<String>();
}
public List<String> argumentSignatures() {
return new ArrayList<String>();
}
Type argumentType(int index) throws ClassNotLoadedException {
throw new ClassNotLoadedException("type unknown");
}
public List<Type> argumentTypes() throws ClassNotLoadedException {
return new ArrayList<Type>();
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 1998, 2003, 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.io.IOException;
public class Packet extends Object {
public final static short NoFlags = 0x0;
public final static short Reply = 0x80;
public final static short ReplyNoError = 0x0;
static int uID = 1;
final static byte[] nullData = new byte[0];
// Note! flags, cmdSet, and cmd are all byte values.
// We represent them as shorts to make them easier
// to work with.
int id;
short flags;
short cmdSet;
short cmd;
short errorCode;
byte[] data;
volatile boolean replied = false;
/**
* Return byte representation of the packet
*/
public byte[] toByteArray() {
int len = data.length + 11;
byte b[] = new byte[len];
b[0] = (byte)((len >>> 24) & 0xff);
b[1] = (byte)((len >>> 16) & 0xff);
b[2] = (byte)((len >>> 8) & 0xff);
b[3] = (byte)((len >>> 0) & 0xff);
b[4] = (byte)((id >>> 24) & 0xff);
b[5] = (byte)((id >>> 16) & 0xff);
b[6] = (byte)((id >>> 8) & 0xff);
b[7] = (byte)((id >>> 0) & 0xff);
b[8] = (byte)flags;
if ((flags & Packet.Reply) == 0) {
b[9] = (byte)cmdSet;
b[10] = (byte)cmd;
} else {
b[9] = (byte)((errorCode >>> 8) & 0xff);
b[10] = (byte)((errorCode >>> 0) & 0xff);
}
if (data.length > 0) {
System.arraycopy(data, 0, b, 11, data.length);
}
return b;
}
/**
* Create a packet from its byte array representation
*/
public static Packet fromByteArray(byte b[]) throws IOException {
if (b.length < 11) {
throw new IOException("packet is insufficient size");
}
int b0 = b[0] & 0xff;
int b1 = b[1] & 0xff;
int b2 = b[2] & 0xff;
int b3 = b[3] & 0xff;
int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0));
if (len != b.length) {
throw new IOException("length size mis-match");
}
int b4 = b[4] & 0xff;
int b5 = b[5] & 0xff;
int b6 = b[6] & 0xff;
int b7 = b[7] & 0xff;
Packet p = new Packet();
p.id = ((b4 << 24) | (b5 << 16) | (b6 << 8) | (b7 << 0));
p.flags = (short)(b[8] & 0xff);
if ((p.flags & Packet.Reply) == 0) {
p.cmdSet = (short)(b[9] & 0xff);
p.cmd = (short)(b[10] & 0xff);
} else {
short b9 = (short)(b[9] & 0xff);
short b10 = (short)(b[10] & 0xff);
p.errorCode = (short)((b9 << 8) + (b10 << 0));
}
p.data = new byte[b.length - 11];
System.arraycopy(b, 11, p.data, 0, p.data.length);
return p;
}
Packet()
{
id = uniqID();
flags = NoFlags;
data = nullData;
}
static synchronized private int uniqID()
{
/*
* JDWP spec does not require this id to be sequential and
* increasing, but our implementation does. See
* VirtualMachine.notifySuspend, for example.
*/
return uID++;
}
}

View File

@@ -0,0 +1,628 @@
/*
* Copyright (c) 1998, 2008, 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.*;
import java.io.ByteArrayOutputStream;
class PacketStream {
final VirtualMachineImpl vm;
private int inCursor = 0;
final Packet pkt;
private ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
private boolean isCommitted = false;
PacketStream(VirtualMachineImpl vm, int cmdSet, int cmd) {
this.vm = vm;
this.pkt = new Packet();
pkt.cmdSet = (short)cmdSet;
pkt.cmd = (short)cmd;
}
PacketStream(VirtualMachineImpl vm, Packet pkt) {
this.vm = vm;
this.pkt = pkt;
this.isCommitted = true; /* read only stream */
}
int id() {
return pkt.id;
}
void send() {
if (!isCommitted) {
pkt.data = dataStream.toByteArray();
vm.sendToTarget(pkt);
isCommitted = true;
}
}
void waitForReply() throws JDWPException {
if (!isCommitted) {
throw new InternalException("waitForReply without send");
}
vm.waitForTargetReply(pkt);
if (pkt.errorCode != Packet.ReplyNoError) {
throw new JDWPException(pkt.errorCode);
}
}
void writeBoolean(boolean data) {
if(data) {
dataStream.write( 1 );
} else {
dataStream.write( 0 );
}
}
void writeByte(byte data) {
dataStream.write( data );
}
void writeChar(char data) {
dataStream.write( (byte)((data >>> 8) & 0xFF) );
dataStream.write( (byte)((data >>> 0) & 0xFF) );
}
void writeShort(short data) {
dataStream.write( (byte)((data >>> 8) & 0xFF) );
dataStream.write( (byte)((data >>> 0) & 0xFF) );
}
void writeInt(int data) {
dataStream.write( (byte)((data >>> 24) & 0xFF) );
dataStream.write( (byte)((data >>> 16) & 0xFF) );
dataStream.write( (byte)((data >>> 8) & 0xFF) );
dataStream.write( (byte)((data >>> 0) & 0xFF) );
}
void writeLong(long data) {
dataStream.write( (byte)((data >>> 56) & 0xFF) );
dataStream.write( (byte)((data >>> 48) & 0xFF) );
dataStream.write( (byte)((data >>> 40) & 0xFF) );
dataStream.write( (byte)((data >>> 32) & 0xFF) );
dataStream.write( (byte)((data >>> 24) & 0xFF) );
dataStream.write( (byte)((data >>> 16) & 0xFF) );
dataStream.write( (byte)((data >>> 8) & 0xFF) );
dataStream.write( (byte)((data >>> 0) & 0xFF) );
}
void writeFloat(float data) {
writeInt(Float.floatToIntBits(data));
}
void writeDouble(double data) {
writeLong(Double.doubleToLongBits(data));
}
void writeID(int size, long data) {
switch (size) {
case 8:
writeLong(data);
break;
case 4:
writeInt((int)data);
break;
case 2:
writeShort((short)data);
break;
default:
throw new UnsupportedOperationException("JDWP: ID size not supported: " + size);
}
}
void writeNullObjectRef() {
writeObjectRef(0);
}
void writeObjectRef(long data) {
writeID(vm.sizeofObjectRef, data);
}
void writeClassRef(long data) {
writeID(vm.sizeofClassRef, data);
}
void writeMethodRef(long data) {
writeID(vm.sizeofMethodRef, data);
}
void writeFieldRef(long data) {
writeID(vm.sizeofFieldRef, data);
}
void writeFrameRef(long data) {
writeID(vm.sizeofFrameRef, data);
}
void writeByteArray(byte[] data) {
dataStream.write(data, 0, data.length);
}
void writeString(String string) {
try {
byte[] stringBytes = string.getBytes("UTF8");
writeInt(stringBytes.length);
writeByteArray(stringBytes);
} catch (java.io.UnsupportedEncodingException e) {
throw new InternalException("Cannot convert string to UTF8 bytes");
}
}
void writeLocation(Location location) {
ReferenceTypeImpl refType = (ReferenceTypeImpl)location.declaringType();
byte tag;
if (refType instanceof ClassType) {
tag = JDWP.TypeTag.CLASS;
} else if (refType instanceof InterfaceType) {
// It's possible to have executable code in an interface
tag = JDWP.TypeTag.INTERFACE;
} else {
throw new InternalException("Invalid Location");
}
writeByte(tag);
writeClassRef(refType.ref());
writeMethodRef(((MethodImpl)location.method()).ref());
writeLong(location.codeIndex());
}
void writeValue(Value val) {
try {
writeValueChecked(val);
} catch (InvalidTypeException exc) { // should never happen
throw new RuntimeException(
"Internal error: Invalid Tag/Type pair");
}
}
void writeValueChecked(Value val) throws InvalidTypeException {
writeByte(ValueImpl.typeValueKey(val));
writeUntaggedValue(val);
}
void writeUntaggedValue(Value val) {
try {
writeUntaggedValueChecked(val);
} catch (InvalidTypeException exc) { // should never happen
throw new RuntimeException(
"Internal error: Invalid Tag/Type pair");
}
}
void writeUntaggedValueChecked(Value val) throws InvalidTypeException {
byte tag = ValueImpl.typeValueKey(val);
if (isObjectTag(tag)) {
if (val == null) {
writeObjectRef(0);
} else {
if (!(val instanceof ObjectReference)) {
throw new InvalidTypeException();
}
writeObjectRef(((ObjectReferenceImpl)val).ref());
}
} else {
switch (tag) {
case JDWP.Tag.BYTE:
if(!(val instanceof ByteValue))
throw new InvalidTypeException();
writeByte(((PrimitiveValue)val).byteValue());
break;
case JDWP.Tag.CHAR:
if(!(val instanceof CharValue))
throw new InvalidTypeException();
writeChar(((PrimitiveValue)val).charValue());
break;
case JDWP.Tag.FLOAT:
if(!(val instanceof FloatValue))
throw new InvalidTypeException();
writeFloat(((PrimitiveValue)val).floatValue());
break;
case JDWP.Tag.DOUBLE:
if(!(val instanceof DoubleValue))
throw new InvalidTypeException();
writeDouble(((PrimitiveValue)val).doubleValue());
break;
case JDWP.Tag.INT:
if(!(val instanceof IntegerValue))
throw new InvalidTypeException();
writeInt(((PrimitiveValue)val).intValue());
break;
case JDWP.Tag.LONG:
if(!(val instanceof LongValue))
throw new InvalidTypeException();
writeLong(((PrimitiveValue)val).longValue());
break;
case JDWP.Tag.SHORT:
if(!(val instanceof ShortValue))
throw new InvalidTypeException();
writeShort(((PrimitiveValue)val).shortValue());
break;
case JDWP.Tag.BOOLEAN:
if(!(val instanceof BooleanValue))
throw new InvalidTypeException();
writeBoolean(((PrimitiveValue)val).booleanValue());
break;
}
}
}
/**
* Read byte represented as one bytes.
*/
byte readByte() {
byte ret = pkt.data[inCursor];
inCursor += 1;
return ret;
}
/**
* Read boolean represented as one byte.
*/
boolean readBoolean() {
byte ret = readByte();
return (ret != 0);
}
/**
* Read char represented as two bytes.
*/
char readChar() {
int b1, b2;
b1 = pkt.data[inCursor++] & 0xff;
b2 = pkt.data[inCursor++] & 0xff;
return (char)((b1 << 8) + b2);
}
/**
* Read short represented as two bytes.
*/
short readShort() {
int b1, b2;
b1 = pkt.data[inCursor++] & 0xff;
b2 = pkt.data[inCursor++] & 0xff;
return (short)((b1 << 8) + b2);
}
/**
* Read int represented as four bytes.
*/
int readInt() {
int b1,b2,b3,b4;
b1 = pkt.data[inCursor++] & 0xff;
b2 = pkt.data[inCursor++] & 0xff;
b3 = pkt.data[inCursor++] & 0xff;
b4 = pkt.data[inCursor++] & 0xff;
return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
}
/**
* Read long represented as eight bytes.
*/
long readLong() {
long b1,b2,b3,b4;
long b5,b6,b7,b8;
b1 = pkt.data[inCursor++] & 0xff;
b2 = pkt.data[inCursor++] & 0xff;
b3 = pkt.data[inCursor++] & 0xff;
b4 = pkt.data[inCursor++] & 0xff;
b5 = pkt.data[inCursor++] & 0xff;
b6 = pkt.data[inCursor++] & 0xff;
b7 = pkt.data[inCursor++] & 0xff;
b8 = pkt.data[inCursor++] & 0xff;
return ((b1 << 56) + (b2 << 48) + (b3 << 40) + (b4 << 32)
+ (b5 << 24) + (b6 << 16) + (b7 << 8) + b8);
}
/**
* Read float represented as four bytes.
*/
float readFloat() {
return Float.intBitsToFloat(readInt());
}
/**
* Read double represented as eight bytes.
*/
double readDouble() {
return Double.longBitsToDouble(readLong());
}
/**
* Read string represented as four byte length followed by
* characters of the string.
*/
String readString() {
String ret;
int len = readInt();
try {
ret = new String(pkt.data, inCursor, len, "UTF8");
} catch(java.io.UnsupportedEncodingException e) {
System.err.println(e);
ret = "Conversion error!";
}
inCursor += len;
return ret;
}
private long readID(int size) {
switch (size) {
case 8:
return readLong();
case 4:
return (long)readInt();
case 2:
return (long)readShort();
default:
throw new UnsupportedOperationException("JDWP: ID size not supported: " + size);
}
}
/**
* Read object represented as vm specific byte sequence.
*/
long readObjectRef() {
return readID(vm.sizeofObjectRef);
}
long readClassRef() {
return readID(vm.sizeofClassRef);
}
ObjectReferenceImpl readTaggedObjectReference() {
byte typeKey = readByte();
return vm.objectMirror(readObjectRef(), typeKey);
}
ObjectReferenceImpl readObjectReference() {
return vm.objectMirror(readObjectRef());
}
StringReferenceImpl readStringReference() {
long ref = readObjectRef();
return vm.stringMirror(ref);
}
ArrayReferenceImpl readArrayReference() {
long ref = readObjectRef();
return vm.arrayMirror(ref);
}
ThreadReferenceImpl readThreadReference() {
long ref = readObjectRef();
return vm.threadMirror(ref);
}
ThreadGroupReferenceImpl readThreadGroupReference() {
long ref = readObjectRef();
return vm.threadGroupMirror(ref);
}
ClassLoaderReferenceImpl readClassLoaderReference() {
long ref = readObjectRef();
return vm.classLoaderMirror(ref);
}
ClassObjectReferenceImpl readClassObjectReference() {
long ref = readObjectRef();
return vm.classObjectMirror(ref);
}
ReferenceTypeImpl readReferenceType() {
byte tag = readByte();
long ref = readObjectRef();
return vm.referenceType(ref, tag);
}
/**
* Read method reference represented as vm specific byte sequence.
*/
long readMethodRef() {
return readID(vm.sizeofMethodRef);
}
/**
* Read field reference represented as vm specific byte sequence.
*/
long readFieldRef() {
return readID(vm.sizeofFieldRef);
}
/**
* Read field represented as vm specific byte sequence.
*/
Field readField() {
ReferenceTypeImpl refType = readReferenceType();
long fieldRef = readFieldRef();
return refType.getFieldMirror(fieldRef);
}
/**
* Read frame represented as vm specific byte sequence.
*/
long readFrameRef() {
return readID(vm.sizeofFrameRef);
}
/**
* Read a value, first byte describes type of value to read.
*/
ValueImpl readValue() {
byte typeKey = readByte();
return readUntaggedValue(typeKey);
}
ValueImpl readUntaggedValue(byte typeKey) {
ValueImpl val = null;
if (isObjectTag(typeKey)) {
val = vm.objectMirror(readObjectRef(), typeKey);
} else {
switch(typeKey) {
case JDWP.Tag.BYTE:
val = new ByteValueImpl(vm, readByte());
break;
case JDWP.Tag.CHAR:
val = new CharValueImpl(vm, readChar());
break;
case JDWP.Tag.FLOAT:
val = new FloatValueImpl(vm, readFloat());
break;
case JDWP.Tag.DOUBLE:
val = new DoubleValueImpl(vm, readDouble());
break;
case JDWP.Tag.INT:
val = new IntegerValueImpl(vm, readInt());
break;
case JDWP.Tag.LONG:
val = new LongValueImpl(vm, readLong());
break;
case JDWP.Tag.SHORT:
val = new ShortValueImpl(vm, readShort());
break;
case JDWP.Tag.BOOLEAN:
val = new BooleanValueImpl(vm, readBoolean());
break;
case JDWP.Tag.VOID:
val = new VoidValueImpl(vm);
break;
}
}
return val;
}
/**
* Read location represented as vm specific byte sequence.
*/
Location readLocation() {
byte tag = readByte();
long classRef = readObjectRef();
long methodRef = readMethodRef();
long codeIndex = readLong();
if (classRef != 0) {
/* Valid location */
ReferenceTypeImpl refType = vm.referenceType(classRef, tag);
return new LocationImpl(vm, refType, methodRef, codeIndex);
} else {
/* Null location (example: uncaught exception) */
return null;
}
}
byte[] readByteArray(int length) {
byte[] array = new byte[length];
System.arraycopy(pkt.data, inCursor, array, 0, length);
inCursor += length;
return array;
}
List<Value> readArrayRegion() {
byte typeKey = readByte();
int length = readInt();
List<Value> list = new ArrayList<Value>(length);
boolean gettingObjects = isObjectTag(typeKey);
for (int i = 0; i < length; i++) {
/*
* Each object comes back with a type key which might
* identify a more specific type than the type key we
* passed in, so we use it in the decodeValue call.
* (For primitives, we just use the original one)
*/
if (gettingObjects) {
typeKey = readByte();
}
Value value = readUntaggedValue(typeKey);
list.add(value);
}
return list;
}
void writeArrayRegion(List<Value> srcValues) {
writeInt(srcValues.size());
for (int i = 0; i < srcValues.size(); i++) {
Value value = srcValues.get(i);
writeUntaggedValue(value);
}
}
int skipBytes(int n) {
inCursor += n;
return n;
}
byte command() {
return (byte)pkt.cmd;
}
static boolean isObjectTag(byte tag) {
return (tag == JDWP.Tag.OBJECT) ||
(tag == JDWP.Tag.ARRAY) ||
(tag == JDWP.Tag.STRING) ||
(tag == JDWP.Tag.THREAD) ||
(tag == JDWP.Tag.THREAD_GROUP) ||
(tag == JDWP.Tag.CLASS_LOADER) ||
(tag == JDWP.Tag.CLASS_OBJECT);
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
abstract class PrimitiveTypeImpl extends TypeImpl implements PrimitiveType {
PrimitiveTypeImpl(VirtualMachine vm) {
super(vm);
}
/*
* Converts the given primitive value to a value of this type.
*/
abstract PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException;
public String toString() {
return name();
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 1998, 2006, 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.*;
public abstract class PrimitiveValueImpl extends ValueImpl
implements PrimitiveValue {
PrimitiveValueImpl(VirtualMachine aVm) {
super(aVm);
}
abstract public boolean booleanValue();
abstract public byte byteValue();
abstract public char charValue();
abstract public short shortValue();
abstract public int intValue();
abstract public long longValue();
abstract public float floatValue();
abstract public double doubleValue();
/*
* The checked versions of the value accessors throw
* InvalidTypeException if the required conversion is
* narrowing and would result in the loss of information
* (either magnitude or precision).
*
* Default implementations here do no checking; subclasses
* override as necessary to do the proper checking.
*/
byte checkedByteValue() throws InvalidTypeException {
return byteValue();
}
char checkedCharValue() throws InvalidTypeException {
return charValue();
}
short checkedShortValue() throws InvalidTypeException {
return shortValue();
}
int checkedIntValue() throws InvalidTypeException {
return intValue();
}
long checkedLongValue() throws InvalidTypeException {
return longValue();
}
float checkedFloatValue() throws InvalidTypeException {
return floatValue();
}
final boolean checkedBooleanValue() throws InvalidTypeException {
/*
* Always disallow a conversion to boolean from any other
* primitive
*/
if (this instanceof BooleanValue) {
return booleanValue();
} else {
throw new InvalidTypeException("Can't convert non-boolean value to boolean");
}
}
final double checkedDoubleValue() throws InvalidTypeException {
/*
* Can't overflow by converting to double, so this method
* is never overridden
*/
return doubleValue();
}
ValueImpl prepareForAssignmentTo(ValueContainer destination)
throws InvalidTypeException {
return convertForAssignmentTo(destination);
}
ValueImpl convertForAssignmentTo(ValueContainer destination)
throws InvalidTypeException {
/*
* TO DO: Centralize JNI signature knowledge
*/
if (destination.signature().length() > 1) {
throw new InvalidTypeException("Can't assign primitive value to object");
}
if ((destination.signature().charAt(0) == 'Z') &&
(type().signature().charAt(0) != 'Z')) {
throw new InvalidTypeException("Can't assign non-boolean value to a boolean");
}
if ((destination.signature().charAt(0) != 'Z') &&
(type().signature().charAt(0) == 'Z')) {
throw new InvalidTypeException("Can't assign boolean value to an non-boolean");
}
if ("void".equals(destination.typeName())) {
throw new InvalidTypeException("Can't assign primitive value to a void");
}
try {
PrimitiveTypeImpl primitiveType = (PrimitiveTypeImpl)destination.type();
return (ValueImpl)(primitiveType.convert(this));
} catch (ClassNotLoadedException e) {
throw new InternalException("Signature and type inconsistent for: " +
destination.typeName());
}
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 2005, 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 java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Properties;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
/*
* An AttachingConnector that connects to a debuggee by specifying the process
* id (pid) as the connector argument. If the process is a debuggee listening
* on a transport address then this connector reads the transport address
* and attempts to attach to it using the appropriate transport.
*/
public class ProcessAttachingConnector
extends ConnectorImpl implements AttachingConnector
{
/*
* The arguments that this connector supports
*/
static final String ARG_PID = "pid";
static final String ARG_TIMEOUT = "timeout";
com.sun.tools.attach.VirtualMachine vm;
Transport transport;
public ProcessAttachingConnector() {
addStringArgument(
ARG_PID,
getString("process_attaching.pid.label"),
getString("process_attaching.pid"),
"",
true);
addIntegerArgument(
ARG_TIMEOUT,
getString("generic_attaching.timeout.label"), // use generic keys to keep
getString("generic_attaching.timeout"), // resource bundle small
"",
false,
0, Integer.MAX_VALUE);
transport = new Transport() {
public String name() {
return "local";
}
};
}
/**
* Attach to a target VM using the specified address and Connector arguments.
*/
public VirtualMachine attach(Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String pid = argument(ARG_PID, args).value();
String t = argument(ARG_TIMEOUT, args).value();
int timeout = 0;
if (t.length() > 0) {
timeout = Integer.decode(t).intValue();
}
// Use Attach API to attach to target VM and read value of
// sun.jdwp.listenAddress property.
String address = null;
com.sun.tools.attach.VirtualMachine vm = null;
try {
vm = com.sun.tools.attach.VirtualMachine.attach(pid);
Properties props = vm.getAgentProperties();
address = props.getProperty("sun.jdwp.listenerAddress");
} catch (Exception x) {
throw new IOException(x.getMessage());
} finally {
if (vm != null) vm.detach();
}
// check that the property value is formatted correctly
if (address == null) {
throw new IOException("Not a debuggee, or not listening for debugger to attach");
}
int pos = address.indexOf(':');
if (pos < 1) {
throw new IOException("Unable to determine transport endpoint");
}
// parse into transport library name and address
final String lib = address.substring(0, pos);
address = address.substring(pos+1, address.length());
TransportService ts = null;
if (lib.equals("dt_socket")) {
ts = new SocketTransportService();
} else {
if (lib.equals("dt_shmem")) {
try {
Class<?> c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
ts = (TransportService)c.newInstance();
} catch (Exception x) { }
}
}
if (ts == null) {
throw new IOException("Transport " + lib + " not recognized");
}
// connect to the debuggee
Connection connection = ts.attach(address, timeout, 0);
return Bootstrap.virtualMachineManager().createVirtualMachine(connection);
}
public String name() {
return "com.sun.jdi.ProcessAttach";
}
public String description() {
return getString("process_attaching.description");
}
public Transport transport() {
if (transport == null) {
return new Transport() {
public String name() {
return "local";
}
};
}
return transport;
}
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 1999, 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.tools.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import com.sun.jdi.VirtualMachine;
import java.util.Map;
import java.io.IOException;
public class RawCommandLineLauncher extends AbstractLauncher implements LaunchingConnector {
static private final String ARG_COMMAND = "command";
static private final String ARG_ADDRESS = "address";
static private final String ARG_QUOTE = "quote";
TransportService transportService;
Transport transport;
public TransportService transportService() {
return transportService;
}
public Transport transport() {
return transport;
}
public RawCommandLineLauncher() {
super();
try {
Class<?> c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
transportService = (TransportService)c.newInstance();
transport = new Transport() {
public String name() {
return "dt_shmem";
}
};
} catch (ClassNotFoundException x) {
} catch (UnsatisfiedLinkError x) {
} catch (InstantiationException x) {
} catch (IllegalAccessException x) {
};
if (transportService == null) {
transportService = new SocketTransportService();
transport = new Transport() {
public String name() {
return "dt_socket";
}
};
}
addStringArgument(
ARG_COMMAND,
getString("raw.command.label"),
getString("raw.command"),
"",
true);
addStringArgument(
ARG_QUOTE,
getString("raw.quote.label"),
getString("raw.quote"),
"\"",
true);
addStringArgument(
ARG_ADDRESS,
getString("raw.address.label"),
getString("raw.address"),
"",
true);
}
public VirtualMachine
launch(Map<String,? extends Connector.Argument> arguments)
throws IOException, IllegalConnectorArgumentsException,
VMStartException
{
String command = argument(ARG_COMMAND, arguments).value();
String address = argument(ARG_ADDRESS, arguments).value();
String quote = argument(ARG_QUOTE, arguments).value();
if (quote.length() > 1) {
throw new IllegalConnectorArgumentsException("Invalid length",
ARG_QUOTE);
}
TransportService.ListenKey listener = transportService.startListening(address);
try {
return launch(tokenizeCommand(command, quote.charAt(0)),
address, listener, transportService);
} finally {
transportService.stopListening(listener);
}
}
public String name() {
return "com.sun.jdi.RawCommandLineLaunch";
}
public String description() {
return getString("raw.description");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,691 @@
/*
* Copyright (c) 2001, 2013, 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.*;
import java.io.File;
class SDE {
private static final int INIT_SIZE_FILE = 3;
private static final int INIT_SIZE_LINE = 100;
private static final int INIT_SIZE_STRATUM = 3;
static final String BASE_STRATUM_NAME = "Java";
/* for C capatibility */
static final String NullString = null;
private class FileTableRecord {
int fileId;
String sourceName;
String sourcePath; // do not read - use accessor
boolean isConverted = false;
/**
* Return the sourcePath, computing it if not set.
* If set, convert '/' in the sourcePath to the
* local file separator.
*/
String getSourcePath(ReferenceTypeImpl refType) {
if (!isConverted) {
if (sourcePath == null) {
sourcePath = refType.baseSourceDir() + sourceName;
} else {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < sourcePath.length(); ++i) {
char ch = sourcePath.charAt(i);
if (ch == '/') {
buf.append(File.separatorChar);
} else {
buf.append(ch);
}
}
sourcePath = buf.toString();
}
isConverted = true;
}
return sourcePath;
}
}
private class LineTableRecord {
int jplsStart;
int jplsEnd;
int jplsLineInc;
int njplsStart;
int njplsEnd;
int fileId;
}
private class StratumTableRecord {
String id;
int fileIndex;
int lineIndex;
}
class Stratum {
private final int sti; /* stratum index */
private Stratum(int sti) {
this.sti = sti;
}
String id() {
return stratumTable[sti].id;
}
boolean isJava() {
return sti == baseStratumIndex;
}
/**
* Return all the sourceNames for this stratum.
* Look from our starting fileIndex upto the starting
* fileIndex of next stratum - can do this since there
* is always a terminator stratum.
* Default sourceName (the first one) must be first.
*/
List<String> sourceNames(ReferenceTypeImpl refType) {
int i;
int fileIndexStart = stratumTable[sti].fileIndex;
/* one past end */
int fileIndexEnd = stratumTable[sti+1].fileIndex;
List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
for (i = fileIndexStart; i < fileIndexEnd; ++i) {
result.add(fileTable[i].sourceName);
}
return result;
}
/**
* Return all the sourcePaths for this stratum.
* Look from our starting fileIndex upto the starting
* fileIndex of next stratum - can do this since there
* is always a terminator stratum.
* Default sourcePath (the first one) must be first.
*/
List<String> sourcePaths(ReferenceTypeImpl refType) {
int i;
int fileIndexStart = stratumTable[sti].fileIndex;
/* one past end */
int fileIndexEnd = stratumTable[sti+1].fileIndex;
List<String> result = new ArrayList<String>(fileIndexEnd - fileIndexStart);
for (i = fileIndexStart; i < fileIndexEnd; ++i) {
result.add(fileTable[i].getSourcePath(refType));
}
return result;
}
LineStratum lineStratum(ReferenceTypeImpl refType,
int jplsLine) {
int lti = stiLineTableIndex(sti, jplsLine);
if (lti < 0) {
return null;
} else {
return new LineStratum(sti, lti, refType,
jplsLine);
}
}
}
class LineStratum {
private final int sti; /* stratum index */
private final int lti; /* line table index */
private final ReferenceTypeImpl refType;
private final int jplsLine;
private String sourceName = null;
private String sourcePath = null;
private LineStratum(int sti, int lti,
ReferenceTypeImpl refType,
int jplsLine) {
this.sti = sti;
this.lti = lti;
this.refType = refType;
this.jplsLine = jplsLine;
}
public boolean equals(Object obj) {
if (obj instanceof LineStratum) {
LineStratum other = (LineStratum)obj;
return (lti == other.lti) &&
(sti == other.sti) &&
(lineNumber() == other.lineNumber()) &&
(refType.equals(other.refType));
} else {
return false;
}
}
@Override
public int hashCode() {
return (lineNumber() * 17) ^ refType.hashCode();
}
int lineNumber() {
return stiLineNumber(sti, lti, jplsLine);
}
/**
* Fetch the source name and source path for
* this line, converting or constructing
* the source path if needed.
*/
void getSourceInfo() {
if (sourceName != null) {
// already done
return;
}
int fti = stiFileTableIndex(sti, lti);
if (fti == -1) {
throw new InternalError(
"Bad SourceDebugExtension, no matching source id " +
lineTable[lti].fileId + " jplsLine: " + jplsLine);
}
FileTableRecord ftr = fileTable[fti];
sourceName = ftr.sourceName;
sourcePath = ftr.getSourcePath(refType);
}
String sourceName() {
getSourceInfo();
return sourceName;
}
String sourcePath() {
getSourceInfo();
return sourcePath;
}
}
private FileTableRecord[] fileTable = null;
private LineTableRecord[] lineTable = null;
private StratumTableRecord[] stratumTable = null;
private int fileIndex = 0;
private int lineIndex = 0;
private int stratumIndex = 0;
private int currentFileId = 0;
private int defaultStratumIndex = -1;
private int baseStratumIndex = -2; /* so as not to match -1 above */
private int sdePos = 0;
final String sourceDebugExtension;
String jplsFilename = null;
String defaultStratumId = null;
boolean isValid = false;
SDE(String sourceDebugExtension) {
this.sourceDebugExtension = sourceDebugExtension;
decode();
}
SDE() {
this.sourceDebugExtension = null;
createProxyForAbsentSDE();
}
char sdePeek() {
if (sdePos >= sourceDebugExtension.length()) {
syntax();
}
return sourceDebugExtension.charAt(sdePos);
}
char sdeRead() {
if (sdePos >= sourceDebugExtension.length()) {
syntax();
}
return sourceDebugExtension.charAt(sdePos++);
}
void sdeAdvance() {
sdePos++;
}
void syntax() {
throw new InternalError("bad SourceDebugExtension syntax - position " +
sdePos);
}
void syntax(String msg) {
throw new InternalError("bad SourceDebugExtension syntax: " + msg);
}
void assureLineTableSize() {
int len = lineTable == null? 0 : lineTable.length;
if (lineIndex >= len) {
int i;
int newLen = len == 0? INIT_SIZE_LINE : len * 2;
LineTableRecord[] newTable = new LineTableRecord[newLen];
for (i = 0; i < len; ++i) {
newTable[i] = lineTable[i];
}
for (; i < newLen; ++i) {
newTable[i] = new LineTableRecord();
}
lineTable = newTable;
}
}
void assureFileTableSize() {
int len = fileTable == null? 0 : fileTable.length;
if (fileIndex >= len) {
int i;
int newLen = len == 0? INIT_SIZE_FILE : len * 2;
FileTableRecord[] newTable = new FileTableRecord[newLen];
for (i = 0; i < len; ++i) {
newTable[i] = fileTable[i];
}
for (; i < newLen; ++i) {
newTable[i] = new FileTableRecord();
}
fileTable = newTable;
}
}
void assureStratumTableSize() {
int len = stratumTable == null? 0 : stratumTable.length;
if (stratumIndex >= len) {
int i;
int newLen = len == 0? INIT_SIZE_STRATUM : len * 2;
StratumTableRecord[] newTable = new StratumTableRecord[newLen];
for (i = 0; i < len; ++i) {
newTable[i] = stratumTable[i];
}
for (; i < newLen; ++i) {
newTable[i] = new StratumTableRecord();
}
stratumTable = newTable;
}
}
String readLine() {
StringBuffer sb = new StringBuffer();
char ch;
ignoreWhite();
while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
sb.append(ch);
}
// check for CR LF
if ((ch == '\r') && (sdePeek() == '\n')) {
sdeRead();
}
ignoreWhite(); // leading white
return sb.toString();
}
private int defaultStratumTableIndex() {
if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {
defaultStratumIndex =
stratumTableIndex(defaultStratumId);
}
return defaultStratumIndex;
}
int stratumTableIndex(String stratumId) {
int i;
if (stratumId == null) {
return defaultStratumTableIndex();
}
for (i = 0; i < (stratumIndex-1); ++i) {
if (stratumTable[i].id.equals(stratumId)) {
return i;
}
}
return defaultStratumTableIndex();
}
Stratum stratum(String stratumID) {
int sti = stratumTableIndex(stratumID);
return new Stratum(sti);
}
List<String> availableStrata() {
List<String> strata = new ArrayList<String>();
for (int i = 0; i < (stratumIndex-1); ++i) {
StratumTableRecord rec = stratumTable[i];
strata.add(rec.id);
}
return strata;
}
/*****************************
* below functions/methods are written to compile under either Java or C
*
* Needed support functions:
* sdePeek()
* sdeRead()
* sdeAdvance()
* readLine()
* assureLineTableSize()
* assureFileTableSize()
* assureStratumTableSize()
* syntax()
*
* stratumTableIndex(String)
*
* Needed support variables:
* lineTable
* lineIndex
* fileTable
* fileIndex
* currentFileId
*
* Needed types:
* String
*
* Needed constants:
* NullString
*/
void ignoreWhite() {
char ch;
while (((ch = sdePeek()) == ' ') || (ch == '\t')) {
sdeAdvance();
}
}
void ignoreLine() {
char ch;
while (((ch = sdeRead()) != '\n') && (ch != '\r')) {
}
/* check for CR LF */
if ((ch == '\r') && (sdePeek() == '\n')) {
sdeAdvance();
}
ignoreWhite(); /* leading white */
}
int readNumber() {
int value = 0;
char ch;
ignoreWhite();
while (((ch = sdePeek()) >= '0') && (ch <= '9')) {
sdeAdvance();
value = (value * 10) + ch - '0';
}
ignoreWhite();
return value;
}
void storeFile(int fileId, String sourceName, String sourcePath) {
assureFileTableSize();
fileTable[fileIndex].fileId = fileId;
fileTable[fileIndex].sourceName = sourceName;
fileTable[fileIndex].sourcePath = sourcePath;
++fileIndex;
}
void fileLine() {
int hasAbsolute = 0; /* acts as boolean */
int fileId;
String sourceName;
String sourcePath = null;
/* is there an absolute filename? */
if (sdePeek() == '+') {
sdeAdvance();
hasAbsolute = 1;
}
fileId = readNumber();
sourceName = readLine();
if (hasAbsolute == 1) {
sourcePath = readLine();
}
storeFile(fileId, sourceName, sourcePath);
}
void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,
int njplsStart, int njplsEnd, int fileId) {
assureLineTableSize();
lineTable[lineIndex].jplsStart = jplsStart;
lineTable[lineIndex].jplsEnd = jplsEnd;
lineTable[lineIndex].jplsLineInc = jplsLineInc;
lineTable[lineIndex].njplsStart = njplsStart;
lineTable[lineIndex].njplsEnd = njplsEnd;
lineTable[lineIndex].fileId = fileId;
++lineIndex;
}
/**
* Parse line translation info. Syntax is
* <NJ-start-line> [ # <file-id> ] [ , <line-count> ] :
* <J-start-line> [ , <line-increment> ] CR
*/
void lineLine() {
int lineCount = 1;
int lineIncrement = 1;
int njplsStart;
int jplsStart;
njplsStart = readNumber();
/* is there a fileID? */
if (sdePeek() == '#') {
sdeAdvance();
currentFileId = readNumber();
}
/* is there a line count? */
if (sdePeek() == ',') {
sdeAdvance();
lineCount = readNumber();
}
if (sdeRead() != ':') {
syntax();
}
jplsStart = readNumber();
if (sdePeek() == ',') {
sdeAdvance();
lineIncrement = readNumber();
}
ignoreLine(); /* flush the rest */
storeLine(jplsStart,
jplsStart + (lineCount * lineIncrement) -1,
lineIncrement,
njplsStart,
njplsStart + lineCount -1,
currentFileId);
}
/**
* Until the next stratum section, everything after this
* is in stratumId - so, store the current indicies.
*/
void storeStratum(String stratumId) {
/* remove redundant strata */
if (stratumIndex > 0) {
if ((stratumTable[stratumIndex-1].fileIndex
== fileIndex) &&
(stratumTable[stratumIndex-1].lineIndex
== lineIndex)) {
/* nothing changed overwrite it */
--stratumIndex;
}
}
/* store the results */
assureStratumTableSize();
stratumTable[stratumIndex].id = stratumId;
stratumTable[stratumIndex].fileIndex = fileIndex;
stratumTable[stratumIndex].lineIndex = lineIndex;
++stratumIndex;
currentFileId = 0;
}
/**
* The beginning of a stratum's info
*/
void stratumSection() {
storeStratum(readLine());
}
void fileSection() {
ignoreLine();
while (sdePeek() != '*') {
fileLine();
}
}
void lineSection() {
ignoreLine();
while (sdePeek() != '*') {
lineLine();
}
}
/**
* Ignore a section we don't know about.
*/
void ignoreSection() {
ignoreLine();
while (sdePeek() != '*') {
ignoreLine();
}
}
/**
* A base "Java" stratum is always available, though
* it is not in the SourceDebugExtension.
* Create the base stratum.
*/
void createJavaStratum() {
baseStratumIndex = stratumIndex;
storeStratum(BASE_STRATUM_NAME);
storeFile(1, jplsFilename, NullString);
/* JPL line numbers cannot exceed 65535 */
storeLine(1, 65536, 1, 1, 65536, 1);
storeStratum("Aux"); /* in case they don't declare */
}
/**
* Decode a SourceDebugExtension which is in SourceMap format.
* This is the entry point into the recursive descent parser.
*/
void decode() {
/* check for "SMAP" - allow EOF if not ours */
if ((sourceDebugExtension.length() < 4) ||
(sdeRead() != 'S') ||
(sdeRead() != 'M') ||
(sdeRead() != 'A') ||
(sdeRead() != 'P')) {
return; /* not our info */
}
ignoreLine(); /* flush the rest */
jplsFilename = readLine();
defaultStratumId = readLine();
createJavaStratum();
while (true) {
if (sdeRead() != '*') {
syntax();
}
switch (sdeRead()) {
case 'S':
stratumSection();
break;
case 'F':
fileSection();
break;
case 'L':
lineSection();
break;
case 'E':
/* set end points */
storeStratum("*terminator*");
isValid = true;
return;
default:
ignoreSection();
}
}
}
void createProxyForAbsentSDE() {
jplsFilename = null;
defaultStratumId = BASE_STRATUM_NAME;
defaultStratumIndex = stratumIndex;
createJavaStratum();
storeStratum("*terminator*");
}
/***************** query functions ***********************/
private int stiLineTableIndex(int sti, int jplsLine) {
int i;
int lineIndexStart;
int lineIndexEnd;
lineIndexStart = stratumTable[sti].lineIndex;
/* one past end */
lineIndexEnd = stratumTable[sti+1].lineIndex;
for (i = lineIndexStart; i < lineIndexEnd; ++i) {
if ((jplsLine >= lineTable[i].jplsStart) &&
(jplsLine <= lineTable[i].jplsEnd)) {
return i;
}
}
return -1;
}
private int stiLineNumber(int sti, int lti, int jplsLine) {
return lineTable[lti].njplsStart +
(((jplsLine - lineTable[lti].jplsStart) /
lineTable[lti].jplsLineInc));
}
private int fileTableIndex(int sti, int fileId) {
int i;
int fileIndexStart = stratumTable[sti].fileIndex;
/* one past end */
int fileIndexEnd = stratumTable[sti+1].fileIndex;
for (i = fileIndexStart; i < fileIndexEnd; ++i) {
if (fileTable[i].fileId == fileId) {
return i;
}
}
return -1;
}
private int stiFileTableIndex(int sti, int lti) {
return fileTableIndex(sti, lineTable[lti].fileId);
}
boolean isValid() {
return isValid;
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1999, 2013, 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.VirtualMachine;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
/*
* An AttachingConnector that uses the SharedMemoryTransportService
*/
public class SharedMemoryAttachingConnector extends GenericAttachingConnector {
static final String ARG_NAME = "name";
public SharedMemoryAttachingConnector() {
super(new SharedMemoryTransportService());
addStringArgument(
ARG_NAME,
getString("memory_attaching.name.label"),
getString("memory_attaching.name"),
"",
true);
transport = new Transport() {
public String name() {
return "dt_shmem"; // for compatibility reasons
}
};
}
public VirtualMachine
attach(Map<String, ? extends Connector.Argument> arguments)
throws IOException, IllegalConnectorArgumentsException
{
String name = argument(ARG_NAME, arguments).value();
return super.attach(name, arguments);
}
public String name() {
return "com.sun.jdi.SharedMemoryAttach";
}
public String description() {
return getString("memory_attaching.description");
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 1999, 2012, 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 com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import java.io.IOException;
class SharedMemoryConnection extends Connection {
private long id;
private Object receiveLock = new Object();
private Object sendLock = new Object();
private Object closeLock = new Object();
private boolean closed = false;
private native byte receiveByte0(long id) throws IOException;
private native void sendByte0(long id, byte b) throws IOException;
private native void close0(long id);
private native byte[] receivePacket0(long id)throws IOException;
private native void sendPacket0(long id, byte b[]) throws IOException;
// handshake with the target VM
void handshake(long handshakeTimeout) throws IOException {
byte[] hello = "JDWP-Handshake".getBytes("UTF-8");
for (int i=0; i<hello.length; i++) {
sendByte0(id, hello[i]);
}
for (int i=0; i<hello.length; i++) {
byte b = receiveByte0(id);
if (b != hello[i]) {
throw new IOException("handshake failed - unrecognized message from target VM");
}
}
}
SharedMemoryConnection(long id) throws IOException {
this.id = id;
}
public void close() {
synchronized (closeLock) {
if (!closed) {
close0(id);
closed = true;
}
}
}
public boolean isOpen() {
synchronized (closeLock) {
return !closed;
}
}
public byte[] readPacket() throws IOException {
if (!isOpen()) {
throw new ClosedConnectionException("Connection closed");
}
byte b[];
try {
// only one thread may be reading at a time
synchronized (receiveLock) {
b = receivePacket0(id);
}
} catch (IOException ioe) {
if (!isOpen()) {
throw new ClosedConnectionException("Connection closed");
} else {
throw ioe;
}
}
return b;
}
public void writePacket(byte b[]) throws IOException {
if (!isOpen()) {
throw new ClosedConnectionException("Connection closed");
}
/*
* Check the packet size
*/
if (b.length < 11) {
throw new IllegalArgumentException("packet is insufficient size");
}
int b0 = b[0] & 0xff;
int b1 = b[1] & 0xff;
int b2 = b[2] & 0xff;
int b3 = b[3] & 0xff;
int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0));
if (len < 11) {
throw new IllegalArgumentException("packet is insufficient size");
}
/*
* Check that the byte array contains the complete packet
*/
if (len > b.length) {
throw new IllegalArgumentException("length mis-match");
}
try {
// only one thread may be writing at a time
synchronized(sendLock) {
sendPacket0(id, b);
}
} catch (IOException ioe) {
if (!isOpen()) {
throw new ClosedConnectionException("Connection closed");
} else {
throw ioe;
}
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1999, 2013, 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.connect.*;
import com.sun.jdi.connect.spi.*;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
/*
* A ListeningConnector based on the SharedMemoryTransportService
*/
public class SharedMemoryListeningConnector extends GenericListeningConnector {
static final String ARG_NAME = "name";
public SharedMemoryListeningConnector() {
super(new SharedMemoryTransportService());
addStringArgument(
ARG_NAME,
getString("memory_listening.name.label"),
getString("memory_listening.name"),
"",
false);
transport = new Transport() {
public String name() {
return "dt_shmem"; // compatibility
}
};
}
// override startListening so that "name" argument can be
// converted into "address" argument
public String
startListening(Map<String, ? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String name = argument(ARG_NAME, args).value();
// if the name argument isn't specified then we use the default
// address for the transport service.
if (name.length() == 0) {
assert transportService instanceof SharedMemoryTransportService;
SharedMemoryTransportService ts = (SharedMemoryTransportService)transportService;
name = ts.defaultAddress();
}
return super.startListening(name, args);
}
public String name() {
return "com.sun.jdi.SharedMemoryListen";
}
public String description() {
return getString("memory_listening.description");
}
}

View File

@@ -0,0 +1,190 @@
/*
* Copyright (c) 1999, 2012, 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 com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import java.io.IOException;
import java.util.Map;
import java.util.ResourceBundle;
class SharedMemoryTransportService extends TransportService {
private ResourceBundle messages = null;
/**
* The listener returned by startListening
*/
static class SharedMemoryListenKey extends ListenKey {
long id;
String name;
SharedMemoryListenKey(long id, String name) {
this.id = id;
this.name = name;
}
long id() {
return id;
}
void setId(long id) {
this.id = id;
}
public String address() {
return name;
}
public String toString() {
return address();
}
}
SharedMemoryTransportService() {
System.loadLibrary("dt_shmem");
initialize();
}
public String name() {
return "SharedMemory";
}
public String defaultAddress() {
return "javadebug";
}
/**
* Return localized description of this transport service
*/
public String description() {
synchronized (this) {
if (messages == null) {
messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
}
}
return messages.getString("memory_transportservice.description");
}
public Capabilities capabilities() {
return new SharedMemoryTransportServiceCapabilities();
}
private native void initialize();
private native long startListening0(String address) throws IOException;
private native long attach0(String address, long attachTimeout) throws IOException;
private native void stopListening0(long id) throws IOException;
private native long accept0(long id, long acceptTimeout) throws IOException;
private native String name(long id) throws IOException;
public Connection attach(String address, long attachTimeout, long handshakeTimeout) throws IOException {
if (address == null) {
throw new NullPointerException("address is null");
}
long id = attach0(address, attachTimeout);
SharedMemoryConnection conn = new SharedMemoryConnection(id);
conn.handshake(handshakeTimeout);
return conn;
}
public TransportService.ListenKey startListening(String address) throws IOException {
if (address == null || address.length() == 0) {
address = defaultAddress();
}
long id = startListening0(address);
return new SharedMemoryListenKey(id, name(id));
}
public ListenKey startListening() throws IOException {
return startListening(null);
}
public void stopListening(ListenKey listener) throws IOException {
if (!(listener instanceof SharedMemoryListenKey)) {
throw new IllegalArgumentException("Invalid listener");
}
long id;
SharedMemoryListenKey key = (SharedMemoryListenKey)listener;
synchronized (key) {
id = key.id();
if (id == 0) {
throw new IllegalArgumentException("Invalid listener");
}
// invalidate the id
key.setId(0);
}
stopListening0(id);
}
public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException {
if (!(listener instanceof SharedMemoryListenKey)) {
throw new IllegalArgumentException("Invalid listener");
}
long transportId;
SharedMemoryListenKey key = (SharedMemoryListenKey)listener;
synchronized (key) {
transportId = key.id();
if (transportId == 0) {
throw new IllegalArgumentException("Invalid listener");
}
}
// in theory another thread could call stopListening before
// accept0 is called. In that case accept0 will try to accept
// with an invalid "transport id" - this should result in an
// IOException.
long connectId = accept0(transportId, acceptTimeout);
SharedMemoryConnection conn = new SharedMemoryConnection(connectId);
conn.handshake(handshakeTimeout);
return conn;
}
}
class SharedMemoryTransportServiceCapabilities extends TransportService.Capabilities {
public boolean supportsMultipleConnections() {
return false;
}
public boolean supportsAttachTimeout() {
return true;
}
public boolean supportsAcceptTimeout() {
return true;
}
public boolean supportsHandshakeTimeout() {
return false;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class ShortTypeImpl extends PrimitiveTypeImpl implements ShortType {
ShortTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.SHORT);
}
PrimitiveValue convert(PrimitiveValue value) throws InvalidTypeException {
return vm.mirrorOf(((PrimitiveValueImpl)value).checkedShortValue());
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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.*;
public class ShortValueImpl extends PrimitiveValueImpl
implements ShortValue {
private short value;
ShortValueImpl(VirtualMachine aVm,short aValue) {
super(aVm);
value = aValue;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof ShortValue)) {
return (value == ((ShortValue)obj).value()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return intValue();
}
public int compareTo(ShortValue obj) {
short other = obj.value();
return value() - other;
}
public Type type() {
return vm.theShortType();
}
public short value() {
return value;
}
public boolean booleanValue() {
return(value == 0)?false:true;
}
public byte byteValue() {
return(byte)value;
}
public char charValue() {
return(char)value;
}
public short shortValue() {
return value;
}
public int intValue() {
return(int)value;
}
public long longValue() {
return(long)value;
}
public float floatValue() {
return(float)value;
}
public double doubleValue() {
return(double)value;
}
byte checkedByteValue() throws InvalidTypeException {
if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to byte");
} else {
return super.checkedByteValue();
}
}
char checkedCharValue() throws InvalidTypeException {
if ((value > Character.MAX_VALUE) || (value < Character.MIN_VALUE)) {
throw new InvalidTypeException("Can't convert " + value + " to char");
} else {
return super.checkedCharValue();
}
}
public String toString() {
return "" + value;
}
byte typeValueKey() {
return JDWP.Tag.SHORT;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 1998, 2013, 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.VirtualMachine;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
/*
* An AttachingConnector that uses the SocketTransportService
*/
public class SocketAttachingConnector extends GenericAttachingConnector {
static final String ARG_PORT = "port";
static final String ARG_HOST = "hostname";
public SocketAttachingConnector() {
super(new SocketTransportService());
String defaultHostName;
try {
defaultHostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
defaultHostName = "";
}
addStringArgument(
ARG_HOST,
getString("socket_attaching.host.label"),
getString("socket_attaching.host"),
defaultHostName,
false);
addIntegerArgument(
ARG_PORT,
getString("socket_attaching.port.label"),
getString("socket_attaching.port"),
"",
true,
0, Integer.MAX_VALUE);
transport = new Transport() {
public String name() {
return "dt_socket"; // for compatibility reasons
}
};
}
/*
* Create an "address" from the hostname and port connector
* arguments and attach to the target VM.
*/
public VirtualMachine
attach(Map<String,? extends Connector.Argument> arguments)
throws IOException, IllegalConnectorArgumentsException
{
String host = argument(ARG_HOST, arguments).value();
if (host.length() > 0) {
host = host + ":";
}
String address = host + argument(ARG_PORT, arguments).value();
return super.attach(address, arguments);
}
public String name() {
return "com.sun.jdi.SocketAttach";
}
public String description() {
return getString("socket_attaching.description");
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 1998, 2018, 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.connect.*;
import com.sun.jdi.connect.spi.*;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import com.sun.jdi.connect.spi.TransportService;
/*
* An ListeningConnector that uses the SocketTransportService
*/
public class SocketListeningConnector extends GenericListeningConnector {
static final String ARG_PORT = "port";
static final String ARG_LOCALADDR = "localAddress";
public SocketListeningConnector() {
super(new SocketTransportService());
addIntegerArgument(
ARG_PORT,
getString("socket_listening.port.label"),
getString("socket_listening.port"),
"",
false,
0, Integer.MAX_VALUE);
addStringArgument(
ARG_LOCALADDR,
getString("socket_listening.localaddr.label"),
getString("socket_listening.localaddr"),
"", // default is wildcard
false);
transport = new Transport() {
public String name() {
return "dt_socket"; // for compatibility reasons
}
};
}
public String
startListening(Map<String,? extends Connector.Argument> args)
throws IOException, IllegalConnectorArgumentsException
{
String port = argument(ARG_PORT, args).value();
String localaddr = argument(ARG_LOCALADDR, args).value();
// default to system chosen port
if (port.length() == 0) {
port = "0";
}
if (localaddr.length() > 0) {
localaddr = localaddr + ":" + port;
} else {
localaddr = port;
}
return super.startListening(localaddr, args);
}
public String name() {
return "com.sun.jdi.SocketListen";
}
public String description() {
return getString("socket_listening.description");
}
// If the port is auto detected update the argument map with the bound port number.
@Override
protected void updateArgumentMapIfRequired(
Map<String, ? extends Connector.Argument> args, TransportService.ListenKey listener) {
if (isWildcardPort(args)) {
String[] address = listener.address().split(":");
if (address.length > 1) {
args.get(ARG_PORT).setValue(address[1]);
}
}
}
private boolean isWildcardPort(Map<String, ? extends Connector.Argument> args) {
String port = args.get(ARG_PORT).value();
return port.isEmpty() || Integer.valueOf(port) == 0;
}
}

View File

@@ -0,0 +1,536 @@
/*
* Copyright (c) 1998, 2003, 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 com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import java.net.*;
import java.io.*;
import java.util.Map;
import java.util.ResourceBundle;
/*
* A transport service based on a TCP connection between the
* debugger and debugee.
*/
public class SocketTransportService extends TransportService {
private ResourceBundle messages = null;
/**
* The listener returned by startListening encapsulates
* the ServerSocket.
*/
static class SocketListenKey extends ListenKey {
ServerSocket ss;
SocketListenKey(ServerSocket ss) {
this.ss = ss;
}
ServerSocket socket() {
return ss;
}
/*
* Returns the string representation of the address that this
* listen key represents.
*/
public String address() {
InetAddress address = ss.getInetAddress();
/*
* If bound to the wildcard address then use current local
* hostname. In the event that we don't know our own hostname
* then assume that host supports IPv4 and return something to
* represent the loopback address.
*/
if (address.isAnyLocalAddress()) {
try {
address = InetAddress.getLocalHost();
} catch (UnknownHostException uhe) {
byte[] loopback = {0x7f,0x00,0x00,0x01};
try {
address = InetAddress.getByAddress("127.0.0.1", loopback);
} catch (UnknownHostException x) {
throw new InternalError("unable to get local hostname");
}
}
}
/*
* Now decide if we return a hostname or IP address. Where possible
* return a hostname but in the case that we are bound to an
* address that isn't registered in the name service then we
* return an address.
*/
String result;
String hostname = address.getHostName();
String hostaddr = address.getHostAddress();
if (hostname.equals(hostaddr)) {
if (address instanceof Inet6Address) {
result = "[" + hostaddr + "]";
} else {
result = hostaddr;
}
} else {
result = hostname;
}
/*
* Finally return "hostname:port", "ipv4-address:port" or
* "[ipv6-address]:port".
*/
return result + ":" + ss.getLocalPort();
}
public String toString() {
return address();
}
}
/**
* Handshake with the debuggee
*/
void handshake(Socket s, long timeout) throws IOException {
s.setSoTimeout((int)timeout);
byte[] hello = "JDWP-Handshake".getBytes("UTF-8");
s.getOutputStream().write(hello);
byte[] b = new byte[hello.length];
int received = 0;
while (received < hello.length) {
int n;
try {
n = s.getInputStream().read(b, received, hello.length-received);
} catch (SocketTimeoutException x) {
throw new IOException("handshake timeout");
}
if (n < 0) {
s.close();
throw new IOException("handshake failed - connection prematurally closed");
}
received += n;
}
for (int i=0; i<hello.length; i++) {
if (b[i] != hello[i]) {
throw new IOException("handshake failed - unrecognized message from target VM");
}
}
// disable read timeout
s.setSoTimeout(0);
}
/**
* No-arg constructor
*/
public SocketTransportService() {
}
/**
* The name of this transport service
*/
public String name() {
return "Socket";
}
/**
* Return localized description of this transport service
*/
public String description() {
synchronized (this) {
if (messages == null) {
messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
}
}
return messages.getString("socket_transportservice.description");
}
/**
* Return the capabilities of this transport service
*/
public Capabilities capabilities() {
return new SocketTransportServiceCapabilities();
}
/**
* Attach to the specified address with optional attach and handshake
* timeout.
*/
public Connection attach(String address, long attachTimeout, long handshakeTimeout)
throws IOException {
if (address == null) {
throw new NullPointerException("address is null");
}
if (attachTimeout < 0 || handshakeTimeout < 0) {
throw new IllegalArgumentException("timeout is negative");
}
int splitIndex = address.indexOf(':');
String host;
String portStr;
if (splitIndex < 0) {
host = InetAddress.getLocalHost().getHostName();
portStr = address;
} else {
host = address.substring(0, splitIndex);
portStr = address.substring(splitIndex+1);
}
int port;
try {
port = Integer.decode(portStr).intValue();
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"unable to parse port number in address");
}
// open TCP connection to VM
InetSocketAddress sa = new InetSocketAddress(host, port);
Socket s = new Socket();
try {
s.connect(sa, (int)attachTimeout);
} catch (SocketTimeoutException exc) {
try {
s.close();
} catch (IOException x) { }
throw new TransportTimeoutException("timed out trying to establish connection");
}
// handshake with the target VM
try {
handshake(s, handshakeTimeout);
} catch (IOException exc) {
try {
s.close();
} catch (IOException x) { }
throw exc;
}
return new SocketConnection(s);
}
/*
* Listen on the specified address and port. Return a listener
* that encapsulates the ServerSocket.
*/
ListenKey startListening(String localaddress, int port) throws IOException {
InetSocketAddress sa;
if (localaddress == null) {
sa = new InetSocketAddress(port);
} else {
sa = new InetSocketAddress(localaddress, port);
}
ServerSocket ss = new ServerSocket();
ss.bind(sa);
return new SocketListenKey(ss);
}
/**
* Listen on the specified address
*/
public ListenKey startListening(String address) throws IOException {
// use ephemeral port if address isn't specified.
if (address == null || address.length() == 0) {
address = "0";
}
int splitIndex = address.indexOf(':');
String localaddr = null;
if (splitIndex >= 0) {
localaddr = address.substring(0, splitIndex);
address = address.substring(splitIndex+1);
}
int port;
try {
port = Integer.decode(address).intValue();
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"unable to parse port number in address");
}
return startListening(localaddr, port);
}
/**
* Listen on the default address
*/
public ListenKey startListening() throws IOException {
return startListening(null, 0);
}
/**
* Stop the listener
*/
public void stopListening(ListenKey listener) throws IOException {
if (!(listener instanceof SocketListenKey)) {
throw new IllegalArgumentException("Invalid listener");
}
synchronized (listener) {
ServerSocket ss = ((SocketListenKey)listener).socket();
// if the ServerSocket has been closed it means
// the listener is invalid
if (ss.isClosed()) {
throw new IllegalArgumentException("Invalid listener");
}
ss.close();
}
}
/**
* Accept a connection from a debuggee and handshake with it.
*/
public Connection accept(ListenKey listener, long acceptTimeout, long handshakeTimeout) throws IOException {
if (acceptTimeout < 0 || handshakeTimeout < 0) {
throw new IllegalArgumentException("timeout is negative");
}
if (!(listener instanceof SocketListenKey)) {
throw new IllegalArgumentException("Invalid listener");
}
ServerSocket ss;
// obtain the ServerSocket from the listener - if the
// socket is closed it means the listener is invalid
synchronized (listener) {
ss = ((SocketListenKey)listener).socket();
if (ss.isClosed()) {
throw new IllegalArgumentException("Invalid listener");
}
}
// from here onwards it's possible that the ServerSocket
// may be closed by a call to stopListening - that's okay
// because the ServerSocket methods will throw an
// IOException indicating the socket is closed.
//
// Additionally, it's possible that another thread calls accept
// with a different accept timeout - that creates a same race
// condition between setting the timeout and calling accept.
// As it is such an unlikely scenario (requires both threads
// to be using the same listener we've chosen to ignore the issue).
ss.setSoTimeout((int)acceptTimeout);
Socket s;
try {
s = ss.accept();
} catch (SocketTimeoutException x) {
throw new TransportTimeoutException("timeout waiting for connection");
}
// handshake here
handshake(s, handshakeTimeout);
return new SocketConnection(s);
}
public String toString() {
return name();
}
}
/*
* The Connection returned by attach and accept is one of these
*/
class SocketConnection extends Connection {
private Socket socket;
private boolean closed = false;
private OutputStream socketOutput;
private InputStream socketInput;
private Object receiveLock = new Object();
private Object sendLock = new Object();
private Object closeLock = new Object();
SocketConnection(Socket socket) throws IOException {
this.socket = socket;
socket.setTcpNoDelay(true);
socketInput = socket.getInputStream();
socketOutput = socket.getOutputStream();
}
public void close() throws IOException {
synchronized (closeLock) {
if (closed) {
return;
}
socketOutput.close();
socketInput.close();
socket.close();
closed = true;
}
}
public boolean isOpen() {
synchronized (closeLock) {
return !closed;
}
}
public byte[] readPacket() throws IOException {
if (!isOpen()) {
throw new ClosedConnectionException("connection is closed");
}
synchronized (receiveLock) {
int b1,b2,b3,b4;
// length
try {
b1 = socketInput.read();
b2 = socketInput.read();
b3 = socketInput.read();
b4 = socketInput.read();
} catch (IOException ioe) {
if (!isOpen()) {
throw new ClosedConnectionException("connection is closed");
} else {
throw ioe;
}
}
// EOF
if (b1<0) {
return new byte[0];
}
if (b2<0 || b3<0 || b4<0) {
throw new IOException("protocol error - premature EOF");
}
int len = ((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0));
if (len < 0) {
throw new IOException("protocol error - invalid length");
}
byte b[] = new byte[len];
b[0] = (byte)b1;
b[1] = (byte)b2;
b[2] = (byte)b3;
b[3] = (byte)b4;
int off = 4;
len -= off;
while (len > 0) {
int count;
try {
count = socketInput.read(b, off, len);
} catch (IOException ioe) {
if (!isOpen()) {
throw new ClosedConnectionException("connection is closed");
} else {
throw ioe;
}
}
if (count < 0) {
throw new IOException("protocol error - premature EOF");
}
len -= count;
off += count;
}
return b;
}
}
public void writePacket(byte b[]) throws IOException {
if (!isOpen()) {
throw new ClosedConnectionException("connection is closed");
}
/*
* Check the packet size
*/
if (b.length < 11) {
throw new IllegalArgumentException("packet is insufficient size");
}
int b0 = b[0] & 0xff;
int b1 = b[1] & 0xff;
int b2 = b[2] & 0xff;
int b3 = b[3] & 0xff;
int len = ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0));
if (len < 11) {
throw new IllegalArgumentException("packet is insufficient size");
}
/*
* Check that the byte array contains the complete packet
*/
if (len > b.length) {
throw new IllegalArgumentException("length mis-match");
}
synchronized (sendLock) {
try {
/*
* Send the packet (ignoring any bytes that follow
* the packet in the byte array).
*/
socketOutput.write(b, 0, len);
} catch (IOException ioe) {
if (!isOpen()) {
throw new ClosedConnectionException("connection is closed");
} else {
throw ioe;
}
}
}
}
}
/*
* The capabilities of the socket transport service
*/
class SocketTransportServiceCapabilities extends TransportService.Capabilities {
public boolean supportsMultipleConnections() {
return true;
}
public boolean supportsAttachTimeout() {
return true;
}
public boolean supportsAcceptTimeout() {
return true;
}
public boolean supportsHandshakeTimeout() {
return true;
}
}

View File

@@ -0,0 +1,404 @@
/*
* Copyright (c) 1998, 2008, 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.Map;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Collections;
public class StackFrameImpl extends MirrorImpl
implements StackFrame, ThreadListener
{
/* Once false, frame should not be used.
* access synchronized on (vm.state())
*/
private boolean isValid = true;
private final ThreadReferenceImpl thread;
private final long id;
private final Location location;
private Map<String, LocalVariable> visibleVariables = null;
private ObjectReference thisObject = null;
StackFrameImpl(VirtualMachine vm, ThreadReferenceImpl thread,
long id, Location location) {
super(vm);
this.thread = thread;
this.id = id;
this.location = location;
thread.addListener(this);
}
/*
* ThreadListener implementation
* Must be synchronized since we must protect against
* sending defunct (isValid == false) stack ids to the back-end.
*/
public boolean threadResumable(ThreadAction action) {
synchronized (vm.state()) {
if (isValid) {
isValid = false;
return false; /* remove this stack frame as a listener */
} else {
throw new InternalException(
"Invalid stack frame thread listener");
}
}
}
void validateStackFrame() {
if (!isValid) {
throw new InvalidStackFrameException("Thread has been resumed");
}
}
/**
* Return the frame location.
* Need not be synchronized since it cannot be provably stale.
*/
public Location location() {
validateStackFrame();
return location;
}
/**
* Return the thread holding the frame.
* Need not be synchronized since it cannot be provably stale.
*/
public ThreadReference thread() {
validateStackFrame();
return thread;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof StackFrameImpl)) {
StackFrameImpl other = (StackFrameImpl)obj;
return (id == other.id) &&
(thread().equals(other.thread())) &&
(location().equals(other.location())) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
return (thread().hashCode() << 4) + ((int)id);
}
public ObjectReference thisObject() {
validateStackFrame();
MethodImpl currentMethod = (MethodImpl)location.method();
if (currentMethod.isStatic() || currentMethod.isNative()) {
return null;
} else {
if (thisObject == null) {
PacketStream ps;
/* protect against defunct frame id */
synchronized (vm.state()) {
validateStackFrame();
ps = JDWP.StackFrame.ThisObject.
enqueueCommand(vm, thread, id);
}
/* actually get it, now that order is guaranteed */
try {
thisObject = JDWP.StackFrame.ThisObject.
waitForReply(vm, ps).objectThis;
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.INVALID_FRAMEID:
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD:
throw new InvalidStackFrameException();
default:
throw exc.toJDIException();
}
}
}
}
return thisObject;
}
/**
* Build the visible variable map.
* Need not be synchronized since it cannot be provably stale.
*/
private void createVisibleVariables() throws AbsentInformationException {
if (visibleVariables == null) {
List<LocalVariable> allVariables = location.method().variables();
Map<String, LocalVariable> map = new HashMap<String, LocalVariable>(allVariables.size());
for (LocalVariable variable : allVariables) {
String name = variable.name();
if (variable.isVisible(this)) {
LocalVariable existing = map.get(name);
if ((existing == null) ||
((LocalVariableImpl)variable).hides(existing)) {
map.put(name, variable);
}
}
}
visibleVariables = map;
}
}
/**
* Return the list of visible variable in the frame.
* Need not be synchronized since it cannot be provably stale.
*/
public List<LocalVariable> visibleVariables() throws AbsentInformationException {
validateStackFrame();
createVisibleVariables();
List<LocalVariable> mapAsList = new ArrayList<LocalVariable>(visibleVariables.values());
Collections.sort(mapAsList);
return mapAsList;
}
/**
* Return a particular variable in the frame.
* Need not be synchronized since it cannot be provably stale.
*/
public LocalVariable visibleVariableByName(String name) throws AbsentInformationException {
validateStackFrame();
createVisibleVariables();
return visibleVariables.get(name);
}
public Value getValue(LocalVariable variable) {
List<LocalVariable> list = new ArrayList<LocalVariable>(1);
list.add(variable);
return getValues(list).get(variable);
}
public Map<LocalVariable, Value> getValues(List<? extends LocalVariable> variables) {
validateStackFrame();
validateMirrors(variables);
int count = variables.size();
JDWP.StackFrame.GetValues.SlotInfo[] slots =
new JDWP.StackFrame.GetValues.SlotInfo[count];
for (int i=0; i<count; ++i) {
LocalVariableImpl variable = (LocalVariableImpl)variables.get(i);
if (!variable.isVisible(this)) {
throw new IllegalArgumentException(variable.name() +
" is not valid at this frame location");
}
slots[i] = new JDWP.StackFrame.GetValues.SlotInfo(variable.slot(),
(byte)variable.signature().charAt(0));
}
PacketStream ps;
/* protect against defunct frame id */
synchronized (vm.state()) {
validateStackFrame();
ps = JDWP.StackFrame.GetValues.enqueueCommand(vm, thread, id, slots);
}
/* actually get it, now that order is guaranteed */
ValueImpl[] values;
try {
values = JDWP.StackFrame.GetValues.waitForReply(vm, ps).values;
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.INVALID_FRAMEID:
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD:
throw new InvalidStackFrameException();
default:
throw exc.toJDIException();
}
}
if (count != values.length) {
throw new InternalException(
"Wrong number of values returned from target VM");
}
Map<LocalVariable, Value> map = new HashMap<LocalVariable, Value>(count);
for (int i=0; i<count; ++i) {
LocalVariableImpl variable = (LocalVariableImpl)variables.get(i);
map.put(variable, values[i]);
}
return map;
}
public void setValue(LocalVariable variableIntf, Value valueIntf)
throws InvalidTypeException, ClassNotLoadedException {
validateStackFrame();
validateMirror(variableIntf);
validateMirrorOrNull(valueIntf);
LocalVariableImpl variable = (LocalVariableImpl)variableIntf;
ValueImpl value = (ValueImpl)valueIntf;
if (!variable.isVisible(this)) {
throw new IllegalArgumentException(variable.name() +
" is not valid at this frame location");
}
try {
// Validate and convert value if necessary
value = ValueImpl.prepareForAssignment(value, variable);
JDWP.StackFrame.SetValues.SlotInfo[] slotVals =
new JDWP.StackFrame.SetValues.SlotInfo[1];
slotVals[0] = new JDWP.StackFrame.SetValues.
SlotInfo(variable.slot(), value);
PacketStream ps;
/* protect against defunct frame id */
synchronized (vm.state()) {
validateStackFrame();
ps = JDWP.StackFrame.SetValues.
enqueueCommand(vm, thread, id, slotVals);
}
/* actually set it, now that order is guaranteed */
try {
JDWP.StackFrame.SetValues.waitForReply(vm, ps);
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.INVALID_FRAMEID:
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD:
throw new InvalidStackFrameException();
default:
throw exc.toJDIException();
}
}
} catch (ClassNotLoadedException e) {
/*
* Since we got this exception,
* the variable type must be a reference type. The value
* we're trying to set is null, but if the variable's
* class has not yet been loaded through the enclosing
* class loader, then setting to null is essentially a
* no-op, and we should allow it without an exception.
*/
if (value != null) {
throw e;
}
}
}
public List<Value> getArgumentValues() {
validateStackFrame();
MethodImpl mmm = (MethodImpl)location.method();
List<String> argSigs = mmm.argumentSignatures();
int count = argSigs.size();
JDWP.StackFrame.GetValues.SlotInfo[] slots =
new JDWP.StackFrame.GetValues.SlotInfo[count];
int slot;
if (mmm.isStatic()) {
slot = 0;
} else {
slot = 1;
}
for (int ii = 0; ii < count; ++ii) {
char sigChar = argSigs.get(ii).charAt(0);
slots[ii] = new JDWP.StackFrame.GetValues.SlotInfo(slot++,(byte)sigChar);
if (sigChar == 'J' || sigChar == 'D') {
slot++;
}
}
PacketStream ps;
/* protect against defunct frame id */
synchronized (vm.state()) {
validateStackFrame();
ps = JDWP.StackFrame.GetValues.enqueueCommand(vm, thread, id, slots);
}
ValueImpl[] values;
try {
values = JDWP.StackFrame.GetValues.waitForReply(vm, ps).values;
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.INVALID_FRAMEID:
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD:
throw new InvalidStackFrameException();
default:
throw exc.toJDIException();
}
}
if (count != values.length) {
throw new InternalException(
"Wrong number of values returned from target VM");
}
return Arrays.asList((Value[])values);
}
void pop() throws IncompatibleThreadStateException {
validateStackFrame();
// flush caches and disable caching until command completion
CommandSender sender =
new CommandSender() {
public PacketStream send() {
return JDWP.StackFrame.PopFrames.enqueueCommand(vm,
thread, id);
}
};
try {
PacketStream stream = thread.sendResumingCommand(sender);
JDWP.StackFrame.PopFrames.waitForReply(vm, stream);
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
throw new IncompatibleThreadStateException(
"Thread not current or suspended");
case JDWP.Error.INVALID_THREAD: /* zombie */
throw new IncompatibleThreadStateException("zombie");
case JDWP.Error.NO_MORE_FRAMES:
throw new InvalidStackFrameException(
"No more frames on the stack");
default:
throw exc.toJDIException();
}
}
// enable caching - suspended again
vm.state().freeze();
}
public String toString() {
return location.toString() + " in thread " + thread.toString();
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2001, 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.*;
class StratumLineInfo implements LineInfo {
private final String stratumID;
private final int lineNumber;
private final String sourceName;
private final String sourcePath;
StratumLineInfo(String stratumID, int lineNumber,
String sourceName, String sourcePath) {
this.stratumID = stratumID;
this.lineNumber = lineNumber;
this.sourceName = sourceName;
this.sourcePath = sourcePath;
}
public String liStratum() {
return stratumID;
}
public int liLineNumber() {
return lineNumber;
}
public String liSourceName()
throws AbsentInformationException {
if (sourceName == null) {
throw new AbsentInformationException();
}
return sourceName;
}
public String liSourcePath()
throws AbsentInformationException {
if (sourcePath == null) {
throw new AbsentInformationException();
}
return sourcePath;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class StringReferenceImpl extends ObjectReferenceImpl
implements StringReference
{
private String value;
StringReferenceImpl(VirtualMachine aVm,long aRef) {
super(aVm,aRef);
}
public String value() {
if(value == null) {
// Does not need synchronization, since worst-case
// static info is fetched twice
try {
value = JDWP.StringReference.Value.
process(vm, this).stringValue;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
return value;
}
public String toString() {
return "\"" + value() + "\"";
}
byte typeValueKey() {
return JDWP.Tag.STRING;
}
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright (c) 1998, 2013, 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.tools.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import com.sun.jdi.VirtualMachine;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.io.IOException;
import java.io.File;
public class SunCommandLineLauncher extends AbstractLauncher implements LaunchingConnector {
static private final String ARG_HOME = "home";
static private final String ARG_OPTIONS = "options";
static private final String ARG_MAIN = "main";
static private final String ARG_INIT_SUSPEND = "suspend";
static private final String ARG_QUOTE = "quote";
static private final String ARG_VM_EXEC = "vmexec";
TransportService transportService;
Transport transport;
boolean usingSharedMemory = false;
TransportService transportService() {
return transportService;
}
public Transport transport() {
return transport;
}
public SunCommandLineLauncher() {
super();
/**
* By default this connector uses either the shared memory
* transport or the socket transport
*/
try {
Class<?> c = Class.forName("com.sun.tools.jdi.SharedMemoryTransportService");
transportService = (TransportService)c.newInstance();
transport = new Transport() {
public String name() {
return "dt_shmem";
}
};
usingSharedMemory = true;
} catch (ClassNotFoundException x) {
} catch (UnsatisfiedLinkError x) {
} catch (InstantiationException x) {
} catch (IllegalAccessException x) {
};
if (transportService == null) {
transportService = new SocketTransportService();
transport = new Transport() {
public String name() {
return "dt_socket";
}
};
}
addStringArgument(
ARG_HOME,
getString("sun.home.label"),
getString("sun.home"),
System.getProperty("java.home"),
false);
addStringArgument(
ARG_OPTIONS,
getString("sun.options.label"),
getString("sun.options"),
"",
false);
addStringArgument(
ARG_MAIN,
getString("sun.main.label"),
getString("sun.main"),
"",
true);
addBooleanArgument(
ARG_INIT_SUSPEND,
getString("sun.init_suspend.label"),
getString("sun.init_suspend"),
true,
false);
addStringArgument(
ARG_QUOTE,
getString("sun.quote.label"),
getString("sun.quote"),
"\"",
true);
addStringArgument(
ARG_VM_EXEC,
getString("sun.vm_exec.label"),
getString("sun.vm_exec"),
"java",
true);
}
static boolean hasWhitespace(String string) {
int length = string.length();
for (int i = 0; i < length; i++) {
if (Character.isWhitespace(string.charAt(i))) {
return true;
}
}
return false;
}
public VirtualMachine
launch(Map<String,? extends Connector.Argument> arguments)
throws IOException, IllegalConnectorArgumentsException,
VMStartException
{
VirtualMachine vm;
String home = argument(ARG_HOME, arguments).value();
String options = argument(ARG_OPTIONS, arguments).value();
String mainClassAndArgs = argument(ARG_MAIN, arguments).value();
boolean wait = ((BooleanArgumentImpl)argument(ARG_INIT_SUSPEND,
arguments)).booleanValue();
String quote = argument(ARG_QUOTE, arguments).value();
String exe = argument(ARG_VM_EXEC, arguments).value();
String exePath = null;
if (quote.length() > 1) {
throw new IllegalConnectorArgumentsException("Invalid length",
ARG_QUOTE);
}
if ((options.indexOf("-Djava.compiler=") != -1) &&
(options.toLowerCase().indexOf("-djava.compiler=none") == -1)) {
throw new IllegalConnectorArgumentsException("Cannot debug with a JIT compiler",
ARG_OPTIONS);
}
/*
* Start listening.
* If we're using the shared memory transport then we pick a
* random address rather than using the (fixed) default.
* Random() uses System.currentTimeMillis() as the seed
* which can be a problem on windows (many calls to
* currentTimeMillis can return the same value), so
* we do a few retries if we get an IOException (we
* assume the IOException is the filename is already in use.)
*/
TransportService.ListenKey listenKey;
if (usingSharedMemory) {
Random rr = new Random();
int failCount = 0;
while(true) {
try {
String address = "javadebug" +
String.valueOf(rr.nextInt(100000));
listenKey = transportService().startListening(address);
break;
} catch (IOException ioe) {
if (++failCount > 5) {
throw ioe;
}
}
}
} else {
listenKey = transportService().startListening();
}
String address = listenKey.address();
try {
if (home.length() > 0) {
exePath = home + File.separator + "bin" + File.separator + exe;
} else {
exePath = exe;
}
// Quote only if necessary in case the quote arg value is bogus
if (hasWhitespace(exePath)) {
exePath = quote + exePath + quote;
}
String xrun = "transport=" + transport().name() +
",address=" + address +
",suspend=" + (wait? 'y' : 'n');
// Quote only if necessary in case the quote arg value is bogus
if (hasWhitespace(xrun)) {
xrun = quote + xrun + quote;
}
String command = exePath + ' ' +
options + ' ' +
"-Xdebug " +
"-Xrunjdwp:" + xrun + ' ' +
mainClassAndArgs;
// System.err.println("Command: \"" + command + '"');
vm = launch(tokenizeCommand(command, quote.charAt(0)), address, listenKey,
transportService());
} finally {
transportService().stopListening(listenKey);
}
return vm;
}
public String name() {
return "com.sun.jdi.CommandLineLaunch";
}
public String description() {
return getString("sun.description");
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 1999, 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 java.io.File;
/**
* This class encapsulates platform-specific details of the
* structure of an SDK which has a JRE embedded in it.
*/
class SunSDK {
/**
* Returns the home directory of a Java 2 SDK if the current
* JRE is embedded in one.
*/
static String home() {
File jreHome = new File(System.getProperty("java.home"));
File jreParent = new File(jreHome.getParent());
String jdwpLibName = "bin" + File.separator +
System.mapLibraryName("jdwp");
File jdwpLib = new File(jreParent, jdwpLibName);
return jdwpLib.exists() ? jreParent.getAbsolutePath() : null;
}
}

View File

@@ -0,0 +1,379 @@
/*
* 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.
*/
package com.sun.tools.jdi;
import com.sun.jdi.*;
import com.sun.jdi.event.*;
import com.sun.jdi.connect.spi.Connection;
import com.sun.jdi.event.EventSet;
import java.util.*;
import java.io.IOException;
public class TargetVM implements Runnable {
private Map<String, Packet> waitingQueue = new HashMap<String, Packet>(32,0.75f);
private volatile boolean shouldListen = true;
private List<EventQueue> eventQueues = Collections.synchronizedList(new ArrayList<EventQueue>(2));
private VirtualMachineImpl vm;
private Connection connection;
private Thread readerThread;
private EventController eventController = null;
private boolean eventsHeld = false;
/*
* TO DO: The limit numbers below are somewhat arbitrary and should
* be configurable in the future.
*/
static private final int OVERLOADED_QUEUE = 2000;
static private final int UNDERLOADED_QUEUE = 100;
TargetVM(VirtualMachineImpl vm, Connection connection) {
this.vm = vm;
this.connection = connection;
this.readerThread = new Thread(vm.threadGroupForJDI(),
this, "JDI Target VM Interface");
this.readerThread.setDaemon(true);
}
void start() {
readerThread.start();
}
private void dumpPacket(Packet packet, boolean sending) {
String direction = sending ? "Sending" : "Receiving";
if (sending) {
vm.printTrace(direction + " Command. id=" + packet.id +
", length=" + packet.data.length +
", commandSet=" + packet.cmdSet +
", command=" + packet.cmd +
", flags=" + packet.flags);
} else {
String type = (packet.flags & Packet.Reply) != 0 ?
"Reply" : "Event";
vm.printTrace(direction + " " + type + ". id=" + packet.id +
", length=" + packet.data.length +
", errorCode=" + packet.errorCode +
", flags=" + packet.flags);
}
StringBuffer line = new StringBuffer(80);
line.append("0000: ");
for (int i = 0; i < packet.data.length; i++) {
if ((i > 0) && (i % 16 == 0)) {
vm.printTrace(line.toString());
line.setLength(0);
line.append(String.valueOf(i));
line.append(": ");
int len = line.length();
for (int j = 0; j < 6 - len; j++) {
line.insert(0, '0');
}
}
int val = 0xff & packet.data[i];
String str = Integer.toHexString(val);
if (str.length() == 1) {
line.append('0');
}
line.append(str);
line.append(' ');
}
if (line.length() > 6) {
vm.printTrace(line.toString());
}
}
public void run() {
if ((vm.traceFlags & VirtualMachine.TRACE_SENDS) != 0) {
vm.printTrace("Target VM interface thread running");
}
Packet p=null,p2;
String idString;
while(shouldListen) {
boolean done = false;
try {
byte b[] = connection.readPacket();
if (b.length == 0) {
done = true;
}
p = Packet.fromByteArray(b);
} catch (IOException e) {
done = true;
}
if (done) {
shouldListen = false;
try {
connection.close();
} catch (IOException ioe) { }
break;
}
if ((vm.traceFlags & VirtualMachineImpl.TRACE_RAW_RECEIVES) != 0) {
dumpPacket(p, false);
}
if((p.flags & Packet.Reply) == 0) {
// It's a command
handleVMCommand(p);
} else {
/*if(p.errorCode != Packet.ReplyNoError) {
System.err.println("Packet " + p.id + " returned failure = " + p.errorCode);
}*/
vm.state().notifyCommandComplete(p.id);
idString = String.valueOf(p.id);
synchronized(waitingQueue) {
p2 = waitingQueue.get(idString);
if (p2 != null)
waitingQueue.remove(idString);
}
if(p2 == null) {
// Whoa! a reply without a sender. Problem.
// FIX ME! Need to post an error.
System.err.println("Recieved reply with no sender!");
continue;
}
p2.errorCode = p.errorCode;
p2.data = p.data;
p2.replied = true;
synchronized(p2) {
p2.notify();
}
}
}
// inform the VM mamager that this VM is history
vm.vmManager.disposeVirtualMachine(vm);
if (eventController != null) {
eventController.release();
}
// close down all the event queues
// Closing a queue causes a VMDisconnectEvent to
// be put onto the queue.
synchronized(eventQueues) {
Iterator<EventQueue> iter = eventQueues.iterator();
while (iter.hasNext()) {
((EventQueueImpl)iter.next()).close();
}
}
// indirectly throw VMDisconnectedException to
// command requesters.
synchronized(waitingQueue) {
Iterator<Packet> iter = waitingQueue.values().iterator();
while (iter.hasNext()) {
Packet packet = iter.next();
synchronized(packet) {
packet.notify();
}
}
waitingQueue.clear();
}
if ((vm.traceFlags & VirtualMachine.TRACE_SENDS) != 0) {
vm.printTrace("Target VM interface thread exiting");
}
}
protected void handleVMCommand(Packet p) {
switch (p.cmdSet) {
case JDWP.Event.COMMAND_SET:
handleEventCmdSet(p);
break;
default:
System.err.println("Ignoring cmd " + p.id + "/" +
p.cmdSet + "/" + p.cmd + " from the VM");
return;
}
}
/* Events should not be constructed on this thread (the thread
* which reads all data from the transport). This means that the
* packet cannot be converted to real JDI objects as that may
* involve further communications with the back end which would
* deadlock.
*
* Instead the whole packet is passed for lazy eval by a queue
* reading thread.
*/
protected void handleEventCmdSet(Packet p) {
EventSet eventSet = new EventSetImpl(vm, p);
if (eventSet != null) {
queueEventSet(eventSet);
}
}
private EventController eventController() {
if (eventController == null) {
eventController = new EventController();
}
return eventController;
}
private synchronized void controlEventFlow(int maxQueueSize) {
if (!eventsHeld && (maxQueueSize > OVERLOADED_QUEUE)) {
eventController().hold();
eventsHeld = true;
} else if (eventsHeld && (maxQueueSize < UNDERLOADED_QUEUE)) {
eventController().release();
eventsHeld = false;
}
}
void notifyDequeueEventSet() {
int maxQueueSize = 0;
synchronized(eventQueues) {
Iterator<EventQueue> iter = eventQueues.iterator();
while (iter.hasNext()) {
EventQueueImpl queue = (EventQueueImpl)iter.next();
maxQueueSize = Math.max(maxQueueSize, queue.size());
}
}
controlEventFlow(maxQueueSize);
}
private void queueEventSet(EventSet eventSet) {
int maxQueueSize = 0;
synchronized(eventQueues) {
Iterator<EventQueue> iter = eventQueues.iterator();
while (iter.hasNext()) {
EventQueueImpl queue = (EventQueueImpl)iter.next();
queue.enqueue(eventSet);
maxQueueSize = Math.max(maxQueueSize, queue.size());
}
}
controlEventFlow(maxQueueSize);
}
void send(Packet packet) {
String id = String.valueOf(packet.id);
synchronized(waitingQueue) {
waitingQueue.put(id, packet);
}
if ((vm.traceFlags & VirtualMachineImpl.TRACE_RAW_SENDS) != 0) {
dumpPacket(packet, true);
}
try {
connection.writePacket(packet.toByteArray());
} catch (IOException e) {
throw new VMDisconnectedException(e.getMessage());
}
}
void waitForReply(Packet packet) {
synchronized(packet) {
while ((!packet.replied) && shouldListen) {
try { packet.wait(); } catch (InterruptedException e) {;}
}
if (!packet.replied) {
throw new VMDisconnectedException();
}
}
}
void addEventQueue(EventQueueImpl queue) {
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
vm.printTrace("New event queue added");
}
eventQueues.add(queue);
}
void stopListening() {
if ((vm.traceFlags & VirtualMachine.TRACE_EVENTS) != 0) {
vm.printTrace("Target VM i/f closing event queues");
}
shouldListen = false;
try {
connection.close();
} catch (IOException ioe) { }
}
private class EventController extends Thread {
int controlRequest = 0;
EventController() {
super(vm.threadGroupForJDI(), "JDI Event Control Thread");
setDaemon(true);
setPriority((MAX_PRIORITY + NORM_PRIORITY)/2);
super.start();
}
synchronized void hold() {
controlRequest++;
notifyAll();
}
synchronized void release() {
controlRequest--;
notifyAll();
}
public void run() {
while(true) {
int currentRequest;
synchronized(this) {
while (controlRequest == 0) {
try {wait();} catch (InterruptedException e) {}
if (!shouldListen) {
return;
}
}
currentRequest = controlRequest;
controlRequest = 0;
}
try {
if (currentRequest > 0) {
JDWP.VirtualMachine.HoldEvents.process(vm);
} else {
JDWP.VirtualMachine.ReleaseEvents.process(vm);
}
} catch (JDWPException e) {
/*
* Don't want to terminate the thread, so the
* stack trace is printed and we continue.
*/
e.toJDIException().printStackTrace(System.err);
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1999, 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.EventObject;
/*
* The name "action" is used to avoid confusion
* with JDI events.
*/
class ThreadAction extends EventObject {
private static final long serialVersionUID = 5690763191100515283L;
// Event ids
/*static final int THREAD_SUSPENDED = 1;*/
static final int THREAD_RESUMABLE = 2;
int id;
ThreadAction(ThreadReference thread, int id) {
super(thread);
this.id = id;
}
ThreadReference thread() {
return (ThreadReference)getSource();
}
int id() {
return id;
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.*;
public class ThreadGroupReferenceImpl extends ObjectReferenceImpl
implements ThreadGroupReference, VMListener
{
// Cached components that cannot change
String name;
ThreadGroupReference parent;
boolean triedParent;
// This is cached only while the VM is suspended
private static class Cache extends ObjectReferenceImpl.Cache {
JDWP.ThreadGroupReference.Children kids = null;
}
protected ObjectReferenceImpl.Cache newCache() {
return new Cache();
}
ThreadGroupReferenceImpl(VirtualMachine aVm,long aRef) {
super(aVm,aRef);
vm.state().addListener(this);
}
protected String description() {
return "ThreadGroupReference " + uniqueID();
}
public String name() {
if (name == null) {
// Does not need synchronization, since worst-case
// static info is fetched twice (Thread group name
// cannot change)
try {
name = JDWP.ThreadGroupReference.Name.
process(vm, this).groupName;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
return name;
}
public ThreadGroupReference parent() {
if (!triedParent) {
// Does not need synchronization, since worst-case
// static info is fetched twice (Thread group parent cannot
// change)
try {
parent = JDWP.ThreadGroupReference.Parent.
process(vm, this).parentGroup;
triedParent = true;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
return parent;
}
public void suspend() {
for (ThreadReference thread : threads()) {
thread.suspend();
}
for (ThreadGroupReference threadGroup : threadGroups()) {
threadGroup.suspend();
}
}
public void resume() {
for (ThreadReference thread : threads()) {
thread.resume();
}
for (ThreadGroupReference threadGroup : threadGroups()) {
threadGroup.resume();
}
}
private JDWP.ThreadGroupReference.Children kids() {
JDWP.ThreadGroupReference.Children kids = null;
try {
Cache local = (Cache)getCache();
if (local != null) {
kids = local.kids;
}
if (kids == null) {
kids = JDWP.ThreadGroupReference.Children
.process(vm, this);
if (local != null) {
local.kids = kids;
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching children ");
}
}
}
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return kids;
}
public List<ThreadReference> threads() {
return Arrays.asList((ThreadReference[])kids().childThreads);
}
public List<ThreadGroupReference> threadGroups() {
return Arrays.asList((ThreadGroupReference[])kids().childGroups);
}
public String toString() {
return "instance of " + referenceType().name() +
"(name='" + name() + "', " + "id=" + uniqueID() + ")";
}
byte typeValueKey() {
return JDWP.Tag.THREAD_GROUP;
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 1999, 2013, 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.EventListener;
interface ThreadListener extends EventListener {
boolean threadResumable(ThreadAction action);
/*
* Not needed for current implementation, and hard to implement
* correctly. (See TargetVM.handleEventCmdSet)
* void threadSuspended(ThreadAction action);
*/
}

View File

@@ -0,0 +1,644 @@
/*
* 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.
*/
package com.sun.tools.jdi;
import com.sun.jdi.*;
import com.sun.jdi.request.BreakpointRequest;
import java.util.*;
import java.lang.ref.WeakReference;
public class ThreadReferenceImpl extends ObjectReferenceImpl
implements ThreadReference, VMListener {
static final int SUSPEND_STATUS_SUSPENDED = 0x1;
static final int SUSPEND_STATUS_BREAK = 0x2;
private int suspendedZombieCount = 0;
/*
* Some objects can only be created while a thread is suspended and are valid
* only while the thread remains suspended. Examples are StackFrameImpl
* and MonitorInfoImpl. When the thread resumes, these objects have to be
* marked as invalid so that their methods can throw
* InvalidStackFrameException if they are called. To do this, such objects
* register themselves as listeners of the associated thread. When the
* thread is resumed, its listeners are notified and mark themselves
* invalid.
* Also, note that ThreadReferenceImpl itself caches some info that
* is valid only as long as the thread is suspended. When the thread
* is resumed, that cache must be purged.
* Lastly, note that ThreadReferenceImpl and its super, ObjectReferenceImpl
* cache some info that is only valid as long as the entire VM is suspended.
* If _any_ thread is resumed, this cache must be purged. To handle this,
* both ThreadReferenceImpl and ObjectReferenceImpl register themselves as
* VMListeners so that they get notified when all threads are suspended and
* when any thread is resumed.
*/
// This is cached for the life of the thread
private ThreadGroupReference threadGroup;
// This is cached only while this one thread is suspended. Each time
// the thread is resumed, we abandon the current cache object and
// create a new initialized one.
private static class LocalCache {
JDWP.ThreadReference.Status status = null;
List<StackFrame> frames = null;
int framesStart = -1;
int framesLength = 0;
int frameCount = -1;
List<ObjectReference> ownedMonitors = null;
List<MonitorInfo> ownedMonitorsInfo = null;
ObjectReference contendedMonitor = null;
boolean triedCurrentContended = false;
}
/*
* The localCache instance var is set by resetLocalCache to an initialized
* object as shown above. This occurs when the ThreadReference
* object is created, and when the mirrored thread is resumed.
* The fields are then filled in by the relevant methods as they
* are called. A problem can occur if resetLocalCache is called
* (ie, a resume() is executed) at certain points in the execution
* of some of these methods - see 6751643. To avoid this, each
* method that wants to use this cache must make a local copy of
* this variable and use that. This means that each invocation of
* these methods will use a copy of the cache object that was in
* effect at the point that the copy was made; if a racy resume
* occurs, it won't affect the method's local copy. This means that
* the values returned by these calls may not match the state of
* the debuggee at the time the caller gets the values. EG,
* frameCount() is called and comes up with 5 frames. But before
* it returns this, a resume of the debuggee thread is executed in a
* different debugger thread. The thread is resumed and running at
* the time that the value 5 is returned. Or even worse, the thread
* could be suspended again and have a different number of frames, eg, 24,
* but this call will still return 5.
*/
private LocalCache localCache;
private void resetLocalCache() {
localCache = new LocalCache();
}
// This is cached only while all threads in the VM are suspended
// Yes, someone could change the name of a thread while it is suspended.
private static class Cache extends ObjectReferenceImpl.Cache {
String name = null;
}
protected ObjectReferenceImpl.Cache newCache() {
return new Cache();
}
// Listeners - synchronized on vm.state()
private List<WeakReference<ThreadListener>> listeners = new ArrayList<WeakReference<ThreadListener>>();
ThreadReferenceImpl(VirtualMachine aVm, long aRef) {
super(aVm,aRef);
resetLocalCache();
vm.state().addListener(this);
}
protected String description() {
return "ThreadReference " + uniqueID();
}
/*
* VMListener implementation
*/
public boolean vmNotSuspended(VMAction action) {
if (action.resumingThread() == null) {
// all threads are being resumed
synchronized (vm.state()) {
processThreadAction(new ThreadAction(this,
ThreadAction.THREAD_RESUMABLE));
}
}
/*
* Othewise, only one thread is being resumed:
* if it is us,
* we have already done our processThreadAction to notify our
* listeners when we processed the resume.
* if it is not us,
* we don't want to notify our listeners
* because we are not being resumed.
*/
return super.vmNotSuspended(action);
}
/**
* Note that we only cache the name string while the entire VM is suspended
* because the name can change via Thread.setName arbitrarily while this
* thread is running.
*/
public String name() {
String name = null;
try {
Cache local = (Cache)getCache();
if (local != null) {
name = local.name;
}
if (name == null) {
name = JDWP.ThreadReference.Name.process(vm, this)
.threadName;
if (local != null) {
local.name = name;
}
}
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return name;
}
/*
* Sends a command to the back end which is defined to do an
* implicit vm-wide resume.
*/
PacketStream sendResumingCommand(CommandSender sender) {
synchronized (vm.state()) {
processThreadAction(new ThreadAction(this,
ThreadAction.THREAD_RESUMABLE));
return sender.send();
}
}
public void suspend() {
try {
JDWP.ThreadReference.Suspend.process(vm, this);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
// Don't consider the thread suspended yet. On reply, notifySuspend()
// will be called.
}
public void resume() {
/*
* If it's a zombie, we can just update internal state without
* going to back end.
*/
if (suspendedZombieCount > 0) {
suspendedZombieCount--;
return;
}
PacketStream stream;
synchronized (vm.state()) {
processThreadAction(new ThreadAction(this,
ThreadAction.THREAD_RESUMABLE));
stream = JDWP.ThreadReference.Resume.enqueueCommand(vm, this);
}
try {
JDWP.ThreadReference.Resume.waitForReply(vm, stream);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
public int suspendCount() {
/*
* If it's a zombie, we maintain the count in the front end.
*/
if (suspendedZombieCount > 0) {
return suspendedZombieCount;
}
try {
return JDWP.ThreadReference.SuspendCount.process(vm, this).suspendCount;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
public void stop(ObjectReference throwable) throws InvalidTypeException {
validateMirrorOrNull(throwable);
// Verify that the given object is a Throwable instance
List<ReferenceType> list = vm.classesByName("java.lang.Throwable");
ClassTypeImpl throwableClass = (ClassTypeImpl)list.get(0);
if ((throwable == null) ||
!throwableClass.isAssignableFrom(throwable)) {
throw new InvalidTypeException("Not an instance of Throwable");
}
try {
JDWP.ThreadReference.Stop.process(vm, this,
(ObjectReferenceImpl)throwable);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
public void interrupt() {
try {
JDWP.ThreadReference.Interrupt.process(vm, this);
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
private JDWP.ThreadReference.Status jdwpStatus() {
LocalCache snapshot = localCache;
JDWP.ThreadReference.Status myStatus = snapshot.status;
try {
if (myStatus == null) {
myStatus = JDWP.ThreadReference.Status.process(vm, this);
if ((myStatus.suspendStatus & SUSPEND_STATUS_SUSPENDED) != 0) {
// thread is suspended, we can cache the status.
snapshot.status = myStatus;
}
}
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return myStatus;
}
public int status() {
return jdwpStatus().threadStatus;
}
public boolean isSuspended() {
return ((suspendedZombieCount > 0) ||
((jdwpStatus().suspendStatus & SUSPEND_STATUS_SUSPENDED) != 0));
}
public boolean isAtBreakpoint() {
/*
* TO DO: This fails to take filters into account.
*/
try {
StackFrame frame = frame(0);
Location location = frame.location();
List<BreakpointRequest> requests = vm.eventRequestManager().breakpointRequests();
Iterator<BreakpointRequest> iter = requests.iterator();
while (iter.hasNext()) {
BreakpointRequest request = iter.next();
if (location.equals(request.location())) {
return true;
}
}
return false;
} catch (IndexOutOfBoundsException iobe) {
return false; // no frames on stack => not at breakpoint
} catch (IncompatibleThreadStateException itse) {
// Per the javadoc, not suspended => return false
return false;
}
}
public ThreadGroupReference threadGroup() {
/*
* Thread group can't change, so it's cached once and for all.
*/
if (threadGroup == null) {
try {
threadGroup = JDWP.ThreadReference.ThreadGroup.
process(vm, this).group;
} catch (JDWPException exc) {
throw exc.toJDIException();
}
}
return threadGroup;
}
public int frameCount() throws IncompatibleThreadStateException {
LocalCache snapshot = localCache;
try {
if (snapshot.frameCount == -1) {
snapshot.frameCount = JDWP.ThreadReference.FrameCount
.process(vm, this).frameCount;
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD: /* zombie */
throw new IncompatibleThreadStateException();
default:
throw exc.toJDIException();
}
}
return snapshot.frameCount;
}
public List<StackFrame> frames() throws IncompatibleThreadStateException {
return privateFrames(0, -1);
}
public StackFrame frame(int index) throws IncompatibleThreadStateException {
List<StackFrame> list = privateFrames(index, 1);
return list.get(0);
}
/**
* Is the requested subrange within what has been retrieved?
* local is known to be non-null. Should only be called from
* a sync method.
*/
private boolean isSubrange(LocalCache snapshot,
int start, int length) {
if (start < snapshot.framesStart) {
return false;
}
if (length == -1) {
return (snapshot.framesLength == -1);
}
if (snapshot.framesLength == -1) {
if ((start + length) > (snapshot.framesStart +
snapshot.frames.size())) {
throw new IndexOutOfBoundsException();
}
return true;
}
return ((start + length) <= (snapshot.framesStart + snapshot.framesLength));
}
public List<StackFrame> frames(int start, int length)
throws IncompatibleThreadStateException {
if (length < 0) {
throw new IndexOutOfBoundsException(
"length must be greater than or equal to zero");
}
return privateFrames(start, length);
}
/**
* Private version of frames() allows "-1" to specify all
* remaining frames.
*/
synchronized private List<StackFrame> privateFrames(int start, int length)
throws IncompatibleThreadStateException {
// Lock must be held while creating stack frames so if that two threads
// do this at the same time, one won't clobber the subset created by the other.
LocalCache snapshot = localCache;
try {
if (snapshot.frames == null || !isSubrange(snapshot, start, length)) {
JDWP.ThreadReference.Frames.Frame[] jdwpFrames
= JDWP.ThreadReference.Frames.
process(vm, this, start, length).frames;
int count = jdwpFrames.length;
snapshot.frames = new ArrayList<StackFrame>(count);
for (int i = 0; i<count; i++) {
if (jdwpFrames[i].location == null) {
throw new InternalException("Invalid frame location");
}
StackFrame frame = new StackFrameImpl(vm, this,
jdwpFrames[i].frameID,
jdwpFrames[i].location);
// Add to the frame list
snapshot.frames.add(frame);
}
snapshot.framesStart = start;
snapshot.framesLength = length;
return Collections.unmodifiableList(snapshot.frames);
} else {
int fromIndex = start - snapshot.framesStart;
int toIndex;
if (length == -1) {
toIndex = snapshot.frames.size() - fromIndex;
} else {
toIndex = fromIndex + length;
}
return Collections.unmodifiableList(snapshot.frames.subList(fromIndex, toIndex));
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD: /* zombie */
throw new IncompatibleThreadStateException();
default:
throw exc.toJDIException();
}
}
}
public List<ObjectReference> ownedMonitors() throws IncompatibleThreadStateException {
LocalCache snapshot = localCache;
try {
if (snapshot.ownedMonitors == null) {
snapshot.ownedMonitors = Arrays.asList(
(ObjectReference[])JDWP.ThreadReference.OwnedMonitors.
process(vm, this).owned);
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching owned monitors"+
" (count = " + snapshot.ownedMonitors.size() + ")");
}
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD: /* zombie */
throw new IncompatibleThreadStateException();
default:
throw exc.toJDIException();
}
}
return snapshot.ownedMonitors;
}
public ObjectReference currentContendedMonitor()
throws IncompatibleThreadStateException {
LocalCache snapshot = localCache;
try {
if (snapshot.contendedMonitor == null &&
!snapshot.triedCurrentContended) {
snapshot.contendedMonitor = JDWP.ThreadReference.CurrentContendedMonitor.
process(vm, this).monitor;
snapshot.triedCurrentContended = true;
if ((snapshot.contendedMonitor != null) &&
((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0)) {
vm.printTrace(description() +
" temporarily caching contended monitor"+
" (id = " + snapshot.contendedMonitor.uniqueID() + ")");
}
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD: /* zombie */
throw new IncompatibleThreadStateException();
default:
throw exc.toJDIException();
}
}
return snapshot.contendedMonitor;
}
public List<MonitorInfo> ownedMonitorsAndFrames() throws IncompatibleThreadStateException {
LocalCache snapshot = localCache;
try {
if (snapshot.ownedMonitorsInfo == null) {
JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor[] minfo;
minfo = JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.process(vm, this).owned;
snapshot.ownedMonitorsInfo = new ArrayList<MonitorInfo>(minfo.length);
for (int i=0; i < minfo.length; i++) {
JDWP.ThreadReference.OwnedMonitorsStackDepthInfo.monitor mi =
minfo[i];
MonitorInfo mon = new MonitorInfoImpl(vm, minfo[i].monitor, this, minfo[i].stack_depth);
snapshot.ownedMonitorsInfo.add(mon);
}
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace(description() +
" temporarily caching owned monitors"+
" (count = " + snapshot.ownedMonitorsInfo.size() + ")");
}
}
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.THREAD_NOT_SUSPENDED:
case JDWP.Error.INVALID_THREAD: /* zombie */
throw new IncompatibleThreadStateException();
default:
throw exc.toJDIException();
}
}
return snapshot.ownedMonitorsInfo;
}
public void popFrames(StackFrame frame) throws IncompatibleThreadStateException {
// Note that interface-wise this functionality belongs
// here in ThreadReference, but implementation-wise it
// belongs in StackFrame, so we just forward it.
if (!frame.thread().equals(this)) {
throw new IllegalArgumentException("frame does not belong to this thread");
}
if (!vm.canPopFrames()) {
throw new UnsupportedOperationException(
"target does not support popping frames");
}
((StackFrameImpl)frame).pop();
}
public void forceEarlyReturn(Value returnValue) throws InvalidTypeException,
ClassNotLoadedException,
IncompatibleThreadStateException {
if (!vm.canForceEarlyReturn()) {
throw new UnsupportedOperationException(
"target does not support the forcing of a method to return early");
}
validateMirrorOrNull(returnValue);
StackFrameImpl sf;
try {
sf = (StackFrameImpl)frame(0);
} catch (IndexOutOfBoundsException exc) {
throw new InvalidStackFrameException("No more frames on the stack");
}
sf.validateStackFrame();
MethodImpl meth = (MethodImpl)sf.location().method();
ValueImpl convertedValue = ValueImpl.prepareForAssignment(returnValue,
meth.getReturnValueContainer());
try {
JDWP.ThreadReference.ForceEarlyReturn.process(vm, this, convertedValue);
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.OPAQUE_FRAME:
throw new NativeMethodException();
case JDWP.Error.THREAD_NOT_SUSPENDED:
throw new IncompatibleThreadStateException(
"Thread not suspended");
case JDWP.Error.THREAD_NOT_ALIVE:
throw new IncompatibleThreadStateException(
"Thread has not started or has finished");
case JDWP.Error.NO_MORE_FRAMES:
throw new InvalidStackFrameException(
"No more frames on the stack");
default:
throw exc.toJDIException();
}
}
}
public String toString() {
return "instance of " + referenceType().name() +
"(name='" + name() + "', " + "id=" + uniqueID() + ")";
}
byte typeValueKey() {
return JDWP.Tag.THREAD;
}
void addListener(ThreadListener listener) {
synchronized (vm.state()) {
listeners.add(new WeakReference<ThreadListener>(listener));
}
}
void removeListener(ThreadListener listener) {
synchronized (vm.state()) {
Iterator<WeakReference<ThreadListener>> iter = listeners.iterator();
while (iter.hasNext()) {
WeakReference<ThreadListener> ref = iter.next();
if (listener.equals(ref.get())) {
iter.remove();
break;
}
}
}
}
/**
* Propagate the the thread state change information
* to registered listeners.
* Must be entered while synchronized on vm.state()
*/
private void processThreadAction(ThreadAction action) {
synchronized (vm.state()) {
Iterator<WeakReference<ThreadListener>> iter = listeners.iterator();
while (iter.hasNext()) {
WeakReference<ThreadListener> ref = iter.next();
ThreadListener listener = ref.get();
if (listener != null) {
switch (action.id()) {
case ThreadAction.THREAD_RESUMABLE:
if (!listener.threadResumable(action)) {
iter.remove();
}
break;
}
} else {
// Listener is unreachable; clean up
iter.remove();
}
}
// Discard our local cache
resetLocalCache();
}
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 1998, 2003, 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;
abstract public class TypeComponentImpl extends MirrorImpl
implements TypeComponent
{
protected final long ref;
protected final String name;
protected final String signature;
protected final String genericSignature;
protected final ReferenceTypeImpl declaringType;
private final int modifiers;
TypeComponentImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
long ref,
String name, String signature,
String genericSignature, int modifiers) {
// The generic signature is set when this is created.
super(vm);
this.declaringType = declaringType;
this.ref = ref;
this.name = name;
this.signature = signature;
if (genericSignature != null && genericSignature.length() != 0) {
this.genericSignature = genericSignature;
} else {
this.genericSignature = null;
}
this.modifiers = modifiers;
}
public String name() {
return name;
}
public String signature() {
return signature;
}
public String genericSignature() {
return genericSignature;
}
public int modifiers() {
return modifiers;
}
public ReferenceType declaringType() {
return declaringType;
}
public boolean isStatic() {
return isModifierSet(VMModifiers.STATIC);
}
public boolean isFinal() {
return isModifierSet(VMModifiers.FINAL);
}
public boolean isPrivate() {
return isModifierSet(VMModifiers.PRIVATE);
}
public boolean isPackagePrivate() {
return !isModifierSet(VMModifiers.PRIVATE
| VMModifiers.PROTECTED
| VMModifiers.PUBLIC);
}
public boolean isProtected() {
return isModifierSet(VMModifiers.PROTECTED);
}
public boolean isPublic() {
return isModifierSet(VMModifiers.PUBLIC);
}
public boolean isSynthetic() {
return isModifierSet(VMModifiers.SYNTHETIC);
}
long ref() {
return ref;
}
boolean isModifierSet(int compareBits) {
return (modifiers & compareBits) != 0;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1998, 2005, 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.*;
public abstract class TypeImpl extends MirrorImpl implements Type
{
private String myName = null;
TypeImpl(VirtualMachine vm)
{
super(vm);
}
public abstract String signature();
public String name() {
if (myName == null) {
JNITypeParser parser = new JNITypeParser(signature());
myName = parser.typeName();
}
return myName;
}
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof Type)) {
Type other = (Type)obj;
return signature().equals(other.signature()) &&
super.equals(obj);
} else {
return false;
}
}
public int hashCode() {
return signature().hashCode();
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1999, 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.EventObject;
/*
* The name "action" is used to avoid confusion
* with JDI events.
*/
class VMAction extends EventObject {
private static final long serialVersionUID = -1701944679310296090L;
// Event ids
static final int VM_SUSPENDED = 1;
static final int VM_NOT_SUSPENDED = 2;
int id;
ThreadReference resumingThread;
VMAction(VirtualMachine vm, int id) {
this(vm, null, id);
}
// For id = VM_NOT_SUSPENDED, if resumingThread != null, then it is
// the only thread that is being resumed.
VMAction(VirtualMachine vm, ThreadReference resumingThread, int id) {
super(vm);
this.id = id;
this.resumingThread = resumingThread;
}
VirtualMachine vm() {
return (VirtualMachine)getSource();
}
int id() {
return id;
}
ThreadReference resumingThread() {
return resumingThread;
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 1999, 2000, 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.EventListener;
interface VMListener extends EventListener {
boolean vmSuspended(VMAction action);
boolean vmNotSuspended(VMAction action);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 1998, 2004, 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.*;
public interface VMModifiers
{
int PUBLIC = 0x00000001; /* visible to everyone */
int PRIVATE = 0x00000002; /* visible only to the defining class */
int PROTECTED = 0x00000004; /* visible to subclasses */
int STATIC = 0x00000008; /* instance variable is static */
int FINAL = 0x00000010; /* no further subclassing, overriding */
int SYNCHRONIZED = 0x00000020; /* wrap method call in monitor lock */
int VOLATILE = 0x00000040; /* can cache in registers */
int BRIDGE = 0x00000040; /* Bridge method generated by compiler */
int TRANSIENT = 0x00000080; /* not persistant */
int VARARGS = 0x00000080; /* Method accepts var. args*/
int NATIVE = 0x00000100; /* implemented in C */
int INTERFACE = 0x00000200; /* class is an interface */
int ABSTRACT = 0x00000400; /* no definition provided */
int ENUM_CONSTANT = 0x00004000; /* enum constant field*/
int SYNTHETIC = 0xf0000000; /* not in source code */
}

View File

@@ -0,0 +1,250 @@
/*
* Copyright (c) 1999, 2020, 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.lang.ref.WeakReference;
import java.util.*;
class VMState {
private final VirtualMachineImpl vm;
// Listeners
private final List<WeakReference<VMListener>> listeners = new ArrayList<WeakReference<VMListener>>(); // synchronized (this)
private boolean notifyingListeners = false; // synchronized (this)
/*
* Certain information can be cached only when the entire VM is
* suspended and there are no pending resumes. The field below
* is used to track whether there are pending resumes.
*/
private final Set<Integer> pendingResumeCommands = Collections.synchronizedSet(new HashSet<>());
// This is cached only while the VM is suspended
private static class Cache {
List<ThreadGroupReference> groups = null; // cached Top Level ThreadGroups
List<ThreadReference> threads = null; // cached Threads
}
private Cache cache = null; // synchronized (this)
private static final Cache markerCache = new Cache();
private void disableCache() {
synchronized (this) {
cache = null;
}
}
private void enableCache() {
synchronized (this) {
cache = markerCache;
}
}
private Cache getCache() {
synchronized (this) {
if (cache == markerCache) {
cache = new Cache();
}
return cache;
}
}
VMState(VirtualMachineImpl vm) {
this.vm = vm;
}
/**
* Is the VM currently suspended, for the purpose of caching?
* Must be called synchronized on vm.state()
*/
boolean isSuspended() {
return cache != null;
}
/*
* A JDWP command has been completed (reply has been received).
* Update data that tracks pending resume commands.
*/
void notifyCommandComplete(int id) {
pendingResumeCommands.remove(id);
}
synchronized void freeze() {
if (cache == null && (pendingResumeCommands.isEmpty())) {
/*
* No pending resumes to worry about. The VM is suspended
* and additional state can be cached. Notify all
* interested listeners.
*/
processVMAction(new VMAction(vm, VMAction.VM_SUSPENDED));
enableCache();
}
}
synchronized PacketStream thawCommand(CommandSender sender) {
PacketStream stream = sender.send();
pendingResumeCommands.add(stream.id());
thaw();
return stream;
}
/**
* All threads are resuming
*/
void thaw() {
thaw(null);
}
/**
* Tell listeners to invalidate suspend-sensitive caches.
* If resumingThread != null, then only that thread is being
* resumed.
*/
synchronized void thaw(ThreadReference resumingThread) {
if (cache != null) {
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace("Clearing VM suspended cache");
}
disableCache();
}
processVMAction(new VMAction(vm, resumingThread, VMAction.VM_NOT_SUSPENDED));
}
private synchronized void processVMAction(VMAction action) {
if (!notifyingListeners) {
// Prevent recursion
notifyingListeners = true;
Iterator<WeakReference<VMListener>> iter = listeners.iterator();
while (iter.hasNext()) {
WeakReference<VMListener> ref = iter.next();
VMListener listener = ref.get();
if (listener != null) {
boolean keep = true;
switch (action.id()) {
case VMAction.VM_SUSPENDED:
keep = listener.vmSuspended(action);
break;
case VMAction.VM_NOT_SUSPENDED:
keep = listener.vmNotSuspended(action);
break;
}
if (!keep) {
iter.remove();
}
} else {
// Listener is unreachable; clean up
iter.remove();
}
}
notifyingListeners = false;
}
}
synchronized void addListener(VMListener listener) {
listeners.add(new WeakReference<VMListener>(listener));
}
synchronized boolean hasListener(VMListener listener) {
Iterator<WeakReference<VMListener>> iter = listeners.iterator();
while (iter.hasNext()) {
WeakReference<VMListener> ref = iter.next();
if (listener.equals(ref.get())) {
return true;
}
}
return false;
}
synchronized void removeListener(VMListener listener) {
Iterator<WeakReference<VMListener>> iter = listeners.iterator();
while (iter.hasNext()) {
WeakReference<VMListener> ref = iter.next();
if (listener.equals(ref.get())) {
iter.remove();
break;
}
}
}
List<ThreadReference> allThreads() {
List<ThreadReference> threads = null;
try {
Cache local = getCache();
if (local != null) {
// may be stale when returned, but not provably so
threads = local.threads;
}
if (threads == null) {
threads = Arrays.asList((ThreadReference[])JDWP.VirtualMachine.AllThreads.
process(vm).threads);
if (local != null) {
local.threads = threads;
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace("Caching all threads (count = " +
threads.size() + ") while VM suspended");
}
}
}
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return threads;
}
List<ThreadGroupReference> topLevelThreadGroups() {
List<ThreadGroupReference> groups = null;
try {
Cache local = getCache();
if (local != null) {
groups = local.groups;
}
if (groups == null) {
groups = Arrays.asList(
(ThreadGroupReference[])JDWP.VirtualMachine.TopLevelThreadGroups.
process(vm).groups);
if (local != null) {
local.groups = groups;
if ((vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
vm.printTrace(
"Caching top level thread groups (count = " +
groups.size() + ") while VM suspended");
}
}
}
} catch (JDWPException exc) {
throw exc.toJDIException();
}
return groups;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) 1999, 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.*;
/*
* This interface allows us to pass fields, variables, and
* array components through the same interfaces. This currently allows
* more common code for type checking. In the future we could use it for
* more.
*/
interface ValueContainer {
Type type() throws ClassNotLoadedException;
Type findType(String signature) throws ClassNotLoadedException;
String typeName();
String signature();
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1998, 1999, 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.*;
abstract class ValueImpl extends MirrorImpl implements Value {
ValueImpl(VirtualMachine aVm) {
super(aVm);
}
static ValueImpl prepareForAssignment(Value value,
ValueContainer destination)
throws InvalidTypeException, ClassNotLoadedException {
if (value == null) {
/*
* TO DO: Centralize JNI signature knowledge
*/
if (destination.signature().length() == 1) {
throw new InvalidTypeException("Can't set a primitive type to null");
}
return null; // no further checking or conversion necessary
} else {
return ((ValueImpl)value).prepareForAssignmentTo(destination);
}
}
static byte typeValueKey(Value val) {
if (val == null) {
return JDWP.Tag.OBJECT;
} else {
return ((ValueImpl)val).typeValueKey();
}
}
abstract ValueImpl prepareForAssignmentTo(ValueContainer destination)
throws InvalidTypeException, ClassNotLoadedException;
abstract byte typeValueKey();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
/*
* Copyright (c) 1998, 2008, 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 com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.io.IOException;
import java.util.ServiceLoader;
/* Public for use by com.sun.jdi.Bootstrap */
public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
private List<Connector> connectors = new ArrayList<Connector>();
private LaunchingConnector defaultConnector = null;
private List<VirtualMachine> targets = new ArrayList<VirtualMachine>();
private final ThreadGroup mainGroupForJDI;
private ResourceBundle messages = null;
private int vmSequenceNumber = 0;
private static final int majorVersion = 1;
private static final int minorVersion = 8;
private static final Object lock = new Object();
private static VirtualMachineManagerImpl vmm;
public static VirtualMachineManager virtualMachineManager() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
JDIPermission vmmPermission =
new JDIPermission("virtualMachineManager");
sm.checkPermission(vmmPermission);
}
synchronized (lock) {
if (vmm == null) {
vmm = new VirtualMachineManagerImpl();
}
}
return vmm;
}
protected VirtualMachineManagerImpl() {
/*
* Create a top-level thread group
*/
ThreadGroup top = Thread.currentThread().getThreadGroup();
ThreadGroup parent = null;
while ((parent = top.getParent()) != null) {
top = parent;
}
mainGroupForJDI = new ThreadGroup(top, "JDI main");
/*
* Load the connectors
*/
ServiceLoader<Connector> connectorLoader =
ServiceLoader.load(Connector.class, Connector.class.getClassLoader());
Iterator<Connector> connectors = connectorLoader.iterator();
while (connectors.hasNext()) {
Connector connector;
try {
connector = connectors.next();
} catch (ThreadDeath x) {
throw x;
} catch (Exception x) {
System.err.println(x);
continue;
} catch (Error x) {
System.err.println(x);
continue;
}
addConnector(connector);
}
/*
* Load any transport services and encapsulate them with
* an attaching and listening connector.
*/
ServiceLoader<TransportService> transportLoader =
ServiceLoader.load(TransportService.class,
TransportService.class.getClassLoader());
Iterator<TransportService> transportServices =
transportLoader.iterator();
while (transportServices.hasNext()) {
TransportService transportService;
try {
transportService = transportServices.next();
} catch (ThreadDeath x) {
throw x;
} catch (Exception x) {
System.err.println(x);
continue;
} catch (Error x) {
System.err.println(x);
continue;
}
addConnector(GenericAttachingConnector.create(transportService));
addConnector(GenericListeningConnector.create(transportService));
}
// no connectors found
if (allConnectors().size() == 0) {
throw new Error("no Connectors loaded");
}
// Set the default launcher. In order to be compatible
// 1.2/1.3/1.4 we try to make the default launcher
// "com.sun.jdi.CommandLineLaunch". If this connector
// isn't found then we arbitarly pick the first connector.
//
boolean found = false;
List<LaunchingConnector> launchers = launchingConnectors();
for (LaunchingConnector lc: launchers) {
if (lc.name().equals("com.sun.jdi.CommandLineLaunch")) {
setDefaultConnector(lc);
found = true;
break;
}
}
if (!found && launchers.size() > 0) {
setDefaultConnector(launchers.get(0));
}
}
public LaunchingConnector defaultConnector() {
if (defaultConnector == null) {
throw new Error("no default LaunchingConnector");
}
return defaultConnector;
}
public void setDefaultConnector(LaunchingConnector connector) {
defaultConnector = connector;
}
public List<LaunchingConnector> launchingConnectors() {
List<LaunchingConnector> launchingConnectors = new ArrayList<LaunchingConnector>(connectors.size());
for (Connector connector: connectors) {
if (connector instanceof LaunchingConnector) {
launchingConnectors.add((LaunchingConnector)connector);
}
}
return Collections.unmodifiableList(launchingConnectors);
}
public List<AttachingConnector> attachingConnectors() {
List<AttachingConnector> attachingConnectors = new ArrayList<AttachingConnector>(connectors.size());
for (Connector connector: connectors) {
if (connector instanceof AttachingConnector) {
attachingConnectors.add((AttachingConnector)connector);
}
}
return Collections.unmodifiableList(attachingConnectors);
}
public List<ListeningConnector> listeningConnectors() {
List<ListeningConnector> listeningConnectors = new ArrayList<ListeningConnector>(connectors.size());
for (Connector connector: connectors) {
if (connector instanceof ListeningConnector) {
listeningConnectors.add((ListeningConnector)connector);
}
}
return Collections.unmodifiableList(listeningConnectors);
}
public List<Connector> allConnectors() {
return Collections.unmodifiableList(connectors);
}
public List<VirtualMachine> connectedVirtualMachines() {
return Collections.unmodifiableList(targets);
}
public void addConnector(Connector connector) {
connectors.add(connector);
}
public void removeConnector(Connector connector) {
connectors.remove(connector);
}
public synchronized VirtualMachine createVirtualMachine(
Connection connection,
Process process) throws IOException {
if (!connection.isOpen()) {
throw new IllegalStateException("connection is not open");
}
VirtualMachine vm;
try {
vm = new VirtualMachineImpl(this, connection, process,
++vmSequenceNumber);
} catch (VMDisconnectedException e) {
throw new IOException(e.getMessage());
}
targets.add(vm);
return vm;
}
public VirtualMachine createVirtualMachine(Connection connection) throws IOException {
return createVirtualMachine(connection, null);
}
public void addVirtualMachine(VirtualMachine vm) {
targets.add(vm);
}
void disposeVirtualMachine(VirtualMachine vm) {
targets.remove(vm);
}
public int majorInterfaceVersion() {
return majorVersion;
}
public int minorInterfaceVersion() {
return minorVersion;
}
ThreadGroup mainGroupForJDI() {
return mainGroupForJDI;
}
String getString(String key) {
if (messages == null) {
messages = ResourceBundle.getBundle("com.sun.tools.jdi.resources.jdi");
}
return messages.getString(key);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 1998, 2003, 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.connect.*;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.VirtualMachineManager;
import java.io.IOException;
/**
* VirtualMachineManager SPI
*/
public interface VirtualMachineManagerService extends VirtualMachineManager {
/**
* Replaces the default connector.
*
* @return the default {@link LaunchingConnector}
* @throws java.lang.IllegalArgumentException if the given
* connector is not a member of the list returned by
* {@link #launchingConnectors}
*
* @param connector the new default connector
*/
void setDefaultConnector(LaunchingConnector connector);
/**
* Adds a connector to the list of known connectors.
*
* @param connector the connector to be added
*/
void addConnector(Connector connector);
/**
* Removes a connector from the list of known connectors.
*
* @param connector the connector to be removed
*/
void removeConnector(Connector connector);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 1998, 1999, 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.*;
public class VoidTypeImpl extends TypeImpl implements VoidType {
VoidTypeImpl(VirtualMachine vm) {
super(vm);
}
public String signature() {
return String.valueOf((char)JDWP.Tag.VOID);
}
public String toString() {
return name();
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1998, 2006, 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.*;
public class VoidValueImpl extends ValueImpl implements VoidValue {
VoidValueImpl(VirtualMachine aVm) {
super(aVm);
}
public boolean equals(Object obj) {
return (obj != null) && (obj instanceof VoidValue) && super.equals(obj);
}
public int hashCode() {
/*
* TO DO: Better hash code
*/
return 47245;
}
public Type type() {
return vm.theVoidType();
}
ValueImpl prepareForAssignmentTo(ValueContainer destination)
throws InvalidTypeException {
if ("void".equals(destination.typeName())) {
return this;
}
throw new InvalidTypeException();
}
public String toString() {
return "<void value>";
}
byte typeValueKey() {
return JDWP.Tag.VOID;
}
}

View File

@@ -0,0 +1,62 @@
package com.sun.tools.jdi.resources;
import java.util.ListResourceBundle;
public final class jdi extends ListResourceBundle {
protected final Object[][] getContents() {
return new Object[][] {
{ "false", "false" },
{ "generic_attaching.address", "Address to which to attach for VM connections" },
{ "generic_attaching.address.label", "Address" },
{ "generic_attaching.timeout", "Timeout while waiting to attach " },
{ "generic_attaching.timeout.label", "Timeout" },
{ "generic_listening.address", "Address to listen for VM connections" },
{ "generic_listening.address.label", "Address" },
{ "generic_listening.timeout", "Timeout while waiting for connection" },
{ "generic_listening.timeout.label", "Timeout" },
{ "memory_attaching.description", "Attaches by shared memory to other VMs" },
{ "memory_attaching.name", "Name of the shared memory area to which to attach for VM connections" },
{ "memory_attaching.name.label", "Name" },
{ "memory_listening.description", "Accepts shared memory connections initiated by other VMs" },
{ "memory_listening.name", "Name of the shared memory area at which to listen for VM connection" },
{ "memory_listening.name.label", "Name" },
{ "memory_transportservice.description", "Connects debugger and debugee using a shared memory connection" },
{ "process_attaching.description", "Attaches to debuggee by process-id (pid)" },
{ "process_attaching.pid", "pid" },
{ "process_attaching.pid.label", "Process-id (pid) of debuggee" },
{ "raw.address", "Address from which to listen for a connection after the raw command is run" },
{ "raw.address.label", "Address" },
{ "raw.command", "Raw command to start the debugged application VM" },
{ "raw.command.label", "Command" },
{ "raw.description", "Launches target using user-specified command line and attaches to it" },
{ "raw.quote", "Character used to combine space-delimited text into a single command line argument" },
{ "raw.quote.label", "Quote" },
{ "socket_attaching.description", "Attaches by socket to other VMs" },
{ "socket_attaching.host", "Machine name to which to attach for VM connections" },
{ "socket_attaching.host.label", "Host" },
{ "socket_attaching.port", "Port number to which to attach for VM connections" },
{ "socket_attaching.port.label", "Port" },
{ "socket_listening.description", "Accepts socket connections initiated by other VMs" },
{ "socket_listening.localaddr", "Local address that the listener binds to" },
{ "socket_listening.localaddr.label", "Local address" },
{ "socket_listening.port", "Port number at which to listen for VM connections" },
{ "socket_listening.port.label", "Port" },
{ "socket_transportservice.description", "Connects debugger and debugee using a TCP connection" },
{ "sun.description", "Launches target using Sun Java VM command line and attaches to it" },
{ "sun.home", "Home directory of the SDK or runtime environment used to launch the application" },
{ "sun.home.label", "Home " },
{ "sun.init_suspend", "All threads will be suspended before execution of main" },
{ "sun.init_suspend.label", "Suspend" },
{ "sun.main", "Main class and arguments, or if -jar is an option, the main jar file and arguments" },
{ "sun.main.label", "Main" },
{ "sun.options", "Launched VM options" },
{ "sun.options.label", "Options" },
{ "sun.quote", "Character used to combine space-delimited text into a single command line argument" },
{ "sun.quote.label", "Quote" },
{ "sun.vm_exec", "Name of the Java VM launcher" },
{ "sun.vm_exec.label", "Launcher" },
{ "true", "true" },
{ "version_format", "Java Debug Interface (Reference Implementation) version {0}.{1} \n{2}" },
};
}
}

View File

@@ -0,0 +1,62 @@
package com.sun.tools.jdi.resources;
import java.util.ListResourceBundle;
public final class jdi_ja extends ListResourceBundle {
protected final Object[][] getContents() {
return new Object[][] {
{ "false", "false" },
{ "generic_attaching.address", "VM\u306B\u63A5\u7D9A\u3059\u308B\u30A2\u30C9\u30EC\u30B9" },
{ "generic_attaching.address.label", "\u30A2\u30C9\u30EC\u30B9" },
{ "generic_attaching.timeout", "\u63A5\u7D9A\u3092\u5F85\u3064\u9593\u306E\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8 " },
{ "generic_attaching.timeout.label", "\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8" },
{ "generic_listening.address", "VM\u3078\u306E\u63A5\u7D9A\u3092\u30EA\u30B9\u30CB\u30F3\u30B0\u3059\u308B\u30A2\u30C9\u30EC\u30B9" },
{ "generic_listening.address.label", "\u30A2\u30C9\u30EC\u30B9" },
{ "generic_listening.timeout", "\u63A5\u7D9A\u3092\u5F85\u3064\u9593\u306E\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8" },
{ "generic_listening.timeout.label", "\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8" },
{ "memory_attaching.description", "\u5171\u6709\u30E1\u30E2\u30EA\u30FC\u3067\u305D\u306E\u4ED6\u306EVM\u306B\u63A5\u7D9A\u3057\u307E\u3059" },
{ "memory_attaching.name", "VM\u3078\u306E\u63A5\u7D9A\u306B\u4F7F\u7528\u3055\u308C\u308B\u5171\u6709\u30E1\u30E2\u30EA\u30FC\u9818\u57DF\u540D" },
{ "memory_attaching.name.label", "\u540D\u524D" },
{ "memory_listening.description", "\u305D\u306E\u4ED6\u306EVM\u306B\u3088\u308A\u958B\u59CB\u3055\u308C\u308B\u5171\u6709\u30E1\u30E2\u30EA\u30FC\u63A5\u7D9A\u3092\u53D7\u3051\u5165\u308C\u307E\u3059" },
{ "memory_listening.name", "VM\u3078\u306E\u63A5\u7D9A\u3092\u30EA\u30B9\u30CB\u30F3\u30B0\u3059\u308B\u305F\u3081\u306E\u5171\u6709\u30E1\u30E2\u30EA\u30FC\u9818\u57DF\u540D" },
{ "memory_listening.name.label", "\u540D\u524D" },
{ "memory_transportservice.description", "\u5171\u6709\u30E1\u30E2\u30EA\u30FC\u63A5\u7D9A\u3067\u30C7\u30D0\u30C3\u30AC\u3068\u30BF\u30FC\u30B2\u30C3\u30C8\u3092\u63A5\u7D9A\u3057\u307E\u3059" },
{ "process_attaching.description", "\u30C7\u30D0\u30C3\u30B0\u3059\u308B\u30D7\u30ED\u30BB\u30B9\u306B\u30D7\u30ED\u30BB\u30B9ID (pid)\u3092\u4F7F\u7528\u3057\u3066\u63A5\u7D9A\u3057\u307E\u3059" },
{ "process_attaching.pid", "pid" },
{ "process_attaching.pid.label", "\u30C7\u30D0\u30C3\u30B0\u3059\u308B\u30D7\u30ED\u30BB\u30B9ID (pid)" },
{ "raw.address", "raw\u30B3\u30DE\u30F3\u30C9\u5B9F\u884C\u5F8C\u306B\u63A5\u7D9A\u3092\u30EA\u30B9\u30CB\u30F3\u30B0\u3059\u308B\u30A2\u30C9\u30EC\u30B9" },
{ "raw.address.label", "\u30A2\u30C9\u30EC\u30B9" },
{ "raw.command", "\u30C7\u30D0\u30C3\u30B0\u3059\u308B\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3VM\u3092\u8D77\u52D5\u3055\u305B\u308Braw\u30B3\u30DE\u30F3\u30C9" },
{ "raw.command.label", "\u30B3\u30DE\u30F3\u30C9" },
{ "raw.description", "\u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30B3\u30DE\u30F3\u30C9\u884C\u3092\u4F7F\u7528\u3057\u3066\u30BF\u30FC\u30B2\u30C3\u30C8\u3092\u8D77\u52D5\u3057\u3001\u63A5\u7D9A\u3057\u307E\u3059" },
{ "raw.quote", "\u5358\u4E00\u306E\u30B3\u30DE\u30F3\u30C9\u884C\u5F15\u6570\u5185\u306B\u30B9\u30DA\u30FC\u30B9\u3067\u533A\u5207\u3089\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u7D50\u3073\u4ED8\u3051\u308B\u305F\u3081\u306B\u4F7F\u7528\u3055\u308C\u308B\u6587\u5B57" },
{ "raw.quote.label", "\u5F15\u7528\u7B26" },
{ "socket_attaching.description", "\u30BD\u30B1\u30C3\u30C8\u3067\u305D\u306E\u4ED6\u306EVM\u306B\u63A5\u7D9A\u3057\u307E\u3059" },
{ "socket_attaching.host", "VM\u306B\u63A5\u7D9A\u3059\u308B\u30DE\u30B7\u30F3\u540D" },
{ "socket_attaching.host.label", "\u30DB\u30B9\u30C8" },
{ "socket_attaching.port", "VM\u306B\u63A5\u7D9A\u3059\u308B\u30DD\u30FC\u30C8\u756A\u53F7" },
{ "socket_attaching.port.label", "\u30DD\u30FC\u30C8" },
{ "socket_listening.description", "\u305D\u306E\u4ED6\u306EVM\u306B\u3088\u308A\u958B\u59CB\u3055\u308C\u308B\u30BD\u30B1\u30C3\u30C8\u63A5\u7D9A\u3092\u53D7\u5165\u308C\u307E\u3059" },
{ "socket_listening.localaddr", "\u30EA\u30B9\u30CA\u30FC\u306E\u30D0\u30A4\u30F3\u30C9\u5148\u30ED\u30FC\u30AB\u30EB\u30FB\u30A2\u30C9\u30EC\u30B9" },
{ "socket_listening.localaddr.label", "\u30ED\u30FC\u30AB\u30EB\u30FB\u30A2\u30C9\u30EC\u30B9" },
{ "socket_listening.port", "VM\u3078\u306E\u63A5\u7D9A\u3092\u30EA\u30B9\u30CB\u30F3\u30B0\u3059\u308B\u30DD\u30FC\u30C8\u756A\u53F7" },
{ "socket_listening.port.label", "\u30DD\u30FC\u30C8" },
{ "socket_transportservice.description", "TCP\u63A5\u7D9A\u3067\u30C7\u30D0\u30C3\u30AC\u3068\u30BF\u30FC\u30B2\u30C3\u30C8\u3092\u63A5\u7D9A\u3057\u307E\u3059" },
{ "sun.description", "Sun\u306EJava VM\u30B3\u30DE\u30F3\u30C9\u884C\u3092\u4F7F\u7528\u3057\u3066\u30BF\u30FC\u30B2\u30C3\u30C8\u3092\u8D77\u52D5\u3057\u3001\u63A5\u7D9A\u3057\u307E\u3059" },
{ "sun.home", "SDK\u306E\u30DB\u30FC\u30E0\u30FB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u307E\u305F\u306F\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u8D77\u52D5\u306B\u4F7F\u7528\u3055\u308C\u308B\u5B9F\u884C\u74B0\u5883" },
{ "sun.home.label", "\u30DB\u30FC\u30E0 " },
{ "sun.init_suspend", "\u30E1\u30A4\u30F3\u306E\u5B9F\u884C\u524D\u306B\u3059\u3079\u3066\u306E\u30B9\u30EC\u30C3\u30C9\u304C\u4E2D\u65AD\u3055\u308C\u307E\u3059\u3002" },
{ "sun.init_suspend.label", "\u4E2D\u65AD" },
{ "sun.main", "\u30E1\u30A4\u30F3\u30FB\u30AF\u30E9\u30B9\u3068\u5F15\u6570\u3001\u307E\u305F\u306F-jar\u304C\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5834\u5408\u306B\u306F\u30E1\u30A4\u30F3jar\u30D5\u30A1\u30A4\u30EB\u3068\u5F15\u6570" },
{ "sun.main.label", "\u30E1\u30A4\u30F3" },
{ "sun.options", "\u8D77\u52D5\u3059\u308BVM\u306E\u30AA\u30D7\u30B7\u30E7\u30F3" },
{ "sun.options.label", "\u30AA\u30D7\u30B7\u30E7\u30F3" },
{ "sun.quote", "\u5358\u4E00\u306E\u30B3\u30DE\u30F3\u30C9\u884C\u5F15\u6570\u5185\u306B\u30B9\u30DA\u30FC\u30B9\u3067\u533A\u5207\u3089\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u7D50\u3073\u4ED8\u3051\u308B\u305F\u3081\u306B\u4F7F\u7528\u3055\u308C\u308B\u6587\u5B57" },
{ "sun.quote.label", "\u5F15\u7528\u7B26" },
{ "sun.vm_exec", "Java VM\u8D77\u52D5\u30C4\u30FC\u30EB\u540D" },
{ "sun.vm_exec.label", "\u8D77\u52D5\u30C4\u30FC\u30EB" },
{ "true", "true" },
{ "version_format", "Java Debug Interface(\u30EA\u30D5\u30A1\u30EC\u30F3\u30B9\u5B9F\u88C5)\u30D0\u30FC\u30B8\u30E7\u30F3{0}.{1}\n{2}" },
};
}
}

View File

@@ -0,0 +1,62 @@
package com.sun.tools.jdi.resources;
import java.util.ListResourceBundle;
public final class jdi_zh_CN extends ListResourceBundle {
protected final Object[][] getContents() {
return new Object[][] {
{ "false", "false" },
{ "generic_attaching.address", "VM \u8FDE\u63A5\u6240\u9644\u52A0\u5230\u7684\u5730\u5740" },
{ "generic_attaching.address.label", "\u5730\u5740" },
{ "generic_attaching.timeout", "\u7B49\u5F85\u9644\u52A0\u64CD\u4F5C\u65F6\u7684\u8D85\u65F6" },
{ "generic_attaching.timeout.label", "\u8D85\u65F6" },
{ "generic_listening.address", "\u76D1\u542C VM \u8FDE\u63A5\u65F6\u4F7F\u7528\u7684\u5730\u5740" },
{ "generic_listening.address.label", "\u5730\u5740" },
{ "generic_listening.timeout", "\u7B49\u5F85\u8FDE\u63A5\u65F6\u7684\u8D85\u65F6" },
{ "generic_listening.timeout.label", "\u8D85\u65F6" },
{ "memory_attaching.description", "\u901A\u8FC7\u5171\u4EAB\u5185\u5B58\u9644\u52A0\u5230\u5176\u4ED6 VM" },
{ "memory_attaching.name", "VM \u8FDE\u63A5\u6240\u9644\u52A0\u5230\u7684\u5171\u4EAB\u5185\u5B58\u533A\u57DF\u7684\u540D\u79F0" },
{ "memory_attaching.name.label", "\u540D\u79F0" },
{ "memory_listening.description", "\u63A5\u53D7\u7531\u5176\u4ED6 VM \u542F\u52A8\u7684\u5171\u4EAB\u5185\u5B58\u8FDE\u63A5" },
{ "memory_listening.name", "\u76D1\u542C VM \u8FDE\u63A5\u65F6\u6240\u5728\u7684\u5171\u4EAB\u5185\u5B58\u533A\u57DF\u7684\u540D\u79F0" },
{ "memory_listening.name.label", "\u540D\u79F0" },
{ "memory_transportservice.description", "\u4F7F\u7528\u5171\u4EAB\u5185\u5B58\u8FDE\u63A5\u6765\u8FDE\u63A5\u8C03\u8BD5\u5668\u548C\u88AB\u8C03\u8BD5\u8FDB\u7A0B" },
{ "process_attaching.description", "\u901A\u8FC7\u8FDB\u7A0B ID (PID) \u9644\u52A0\u5230\u88AB\u8C03\u8BD5\u8FDB\u7A0B" },
{ "process_attaching.pid", "PID" },
{ "process_attaching.pid.label", "\u88AB\u8C03\u8BD5\u8FDB\u7A0B\u7684\u8FDB\u7A0B ID (PID)" },
{ "raw.address", "\u8FD0\u884C\u539F\u59CB\u547D\u4EE4\u4E4B\u540E, \u76D1\u542C\u8FDE\u63A5\u65F6\u4F7F\u7528\u7684\u5730\u5740" },
{ "raw.address.label", "\u5730\u5740" },
{ "raw.command", "\u7528\u4E8E\u542F\u52A8\u8C03\u8BD5\u5E94\u7528\u7A0B\u5E8F VM \u7684\u539F\u59CB\u547D\u4EE4" },
{ "raw.command.label", "\u547D\u4EE4" },
{ "raw.description", "\u4F7F\u7528\u7528\u6237\u6307\u5B9A\u7684\u547D\u4EE4\u884C\u542F\u52A8\u76EE\u6807\u5E76\u9644\u52A0\u5230\u8BE5\u76EE\u6807" },
{ "raw.quote", "\u7528\u4E8E\u5C06\u4EE5\u7A7A\u683C\u5206\u9694\u7684\u6587\u672C\u7EC4\u5408\u4E3A\u4E00\u4E2A\u547D\u4EE4\u884C\u53C2\u6570\u7684\u5B57\u7B26" },
{ "raw.quote.label", "\u5F15\u53F7" },
{ "socket_attaching.description", "\u901A\u8FC7\u5957\u63A5\u5B57\u9644\u52A0\u5230\u5176\u4ED6 VM" },
{ "socket_attaching.host", "VM \u8FDE\u63A5\u6240\u9644\u52A0\u5230\u7684\u8BA1\u7B97\u673A\u540D\u79F0" },
{ "socket_attaching.host.label", "\u4E3B\u673A" },
{ "socket_attaching.port", "VM \u8FDE\u63A5\u6240\u9644\u52A0\u5230\u7684\u7AEF\u53E3\u53F7" },
{ "socket_attaching.port.label", "\u7AEF\u53E3" },
{ "socket_listening.description", "\u63A5\u53D7\u7531\u5176\u4ED6 VM \u542F\u52A8\u7684\u5957\u63A5\u5B57\u8FDE\u63A5" },
{ "socket_listening.localaddr", "\u76D1\u542C\u7A0B\u5E8F\u7ED1\u5B9A\u5230\u7684\u672C\u5730\u5730\u5740" },
{ "socket_listening.localaddr.label", "\u672C\u5730\u5730\u5740" },
{ "socket_listening.port", "\u76D1\u542C VM \u8FDE\u63A5\u65F6\u4F7F\u7528\u7684\u7AEF\u53E3\u53F7" },
{ "socket_listening.port.label", "\u7AEF\u53E3" },
{ "socket_transportservice.description", "\u4F7F\u7528 TCP \u8FDE\u63A5\u6765\u8FDE\u63A5\u8C03\u8BD5\u5668\u548C\u88AB\u8C03\u8BD5\u8FDB\u7A0B" },
{ "sun.description", "\u4F7F\u7528 Sun Java VM \u547D\u4EE4\u884C\u542F\u52A8\u76EE\u6807\u5E76\u9644\u52A0\u5230\u8BE5\u76EE\u6807" },
{ "sun.home", "\u7528\u4E8E\u542F\u52A8\u5E94\u7528\u7A0B\u5E8F\u7684 SDK \u6216\u8FD0\u884C\u65F6\u73AF\u5883\u7684\u4E3B\u76EE\u5F55" },
{ "sun.home.label", "\u4E3B\u76EE\u5F55 " },
{ "sun.init_suspend", "\u5728\u6267\u884C\u4E3B\u7C7B\u4E4B\u524D, \u5C06\u6302\u8D77\u6240\u6709\u7EBF\u7A0B" },
{ "sun.init_suspend.label", "\u6302\u8D77" },
{ "sun.main", "\u4E3B\u7C7B\u548C\u53C2\u6570, \u6216\u8005\u5982\u679C -jar \u662F\u4E00\u4E2A\u9009\u9879, \u5219\u4E3A\u4E3B jar \u6587\u4EF6\u548C\u53C2\u6570" },
{ "sun.main.label", "\u4E3B" },
{ "sun.options", "\u5DF2\u542F\u52A8\u7684 VM \u9009\u9879" },
{ "sun.options.label", "\u9009\u9879" },
{ "sun.quote", "\u7528\u4E8E\u5C06\u4EE5\u7A7A\u683C\u5206\u9694\u7684\u6587\u672C\u7EC4\u5408\u4E3A\u4E00\u4E2A\u547D\u4EE4\u884C\u53C2\u6570\u7684\u5B57\u7B26" },
{ "sun.quote.label", "\u5F15\u53F7" },
{ "sun.vm_exec", "Java VM \u542F\u52A8\u7A0B\u5E8F\u7684\u540D\u79F0" },
{ "sun.vm_exec.label", "\u542F\u52A8\u7A0B\u5E8F" },
{ "true", "true" },
{ "version_format", "Java \u8C03\u8BD5\u63A5\u53E3 (\u53C2\u8003\u5B9E\u73B0) \u7248\u672C {0}.{1}\n{2}" },
};
}
}