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,67 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.*;
class AccessWatchpointSpec extends WatchpointSpec {
AccessWatchpointSpec(ReferenceTypeSpec refSpec, String fieldId)
throws MalformedMemberNameException {
super(refSpec, fieldId);
}
/**
* The 'refType' is known to match, return the EventRequest.
*/
@Override
EventRequest resolveEventRequest(ReferenceType refType)
throws NoSuchFieldException {
Field field = refType.fieldByName(fieldId);
EventRequestManager em = refType.virtualMachine().eventRequestManager();
EventRequest wp = em.createAccessWatchpointRequest(field);
wp.setSuspendPolicy(suspendPolicy);
wp.enable();
return wp;
}
@Override
public String toString() {
return MessageOutput.format("watch accesses of",
new Object [] {refSpec.toString(),
fieldId});
}
}

View File

@@ -0,0 +1,50 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
public class AmbiguousMethodException extends Exception
{
private static final long serialVersionUID = -5372629264936918654L;
public AmbiguousMethodException()
{
super();
}
public AmbiguousMethodException(String s)
{
super(s);
}
}

View File

@@ -0,0 +1,391 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.*;
import java.util.ArrayList;
import java.util.List;
class BreakpointSpec extends EventRequestSpec {
String methodId;
List<String> methodArgs;
int lineNumber;
BreakpointSpec(ReferenceTypeSpec refSpec, int lineNumber) {
super(refSpec);
this.methodId = null;
this.methodArgs = null;
this.lineNumber = lineNumber;
}
BreakpointSpec(ReferenceTypeSpec refSpec, String methodId,
List<String> methodArgs) throws MalformedMemberNameException {
super(refSpec);
this.methodId = methodId;
this.methodArgs = methodArgs;
this.lineNumber = 0;
if (!isValidMethodName(methodId)) {
throw new MalformedMemberNameException(methodId);
}
}
/**
* The 'refType' is known to match, return the EventRequest.
*/
@Override
EventRequest resolveEventRequest(ReferenceType refType)
throws AmbiguousMethodException,
AbsentInformationException,
InvalidTypeException,
NoSuchMethodException,
LineNotFoundException {
Location location = location(refType);
if (location == null) {
throw new InvalidTypeException();
}
EventRequestManager em = refType.virtualMachine().eventRequestManager();
EventRequest bp = em.createBreakpointRequest(location);
bp.setSuspendPolicy(suspendPolicy);
bp.enable();
return bp;
}
String methodName() {
return methodId;
}
int lineNumber() {
return lineNumber;
}
List<String> methodArgs() {
return methodArgs;
}
boolean isMethodBreakpoint() {
return (methodId != null);
}
@Override
public int hashCode() {
return refSpec.hashCode() + lineNumber +
((methodId != null) ? methodId.hashCode() : 0) +
((methodArgs != null) ? methodArgs.hashCode() : 0);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BreakpointSpec) {
BreakpointSpec breakpoint = (BreakpointSpec)obj;
return ((methodId != null) ?
methodId.equals(breakpoint.methodId)
: methodId == breakpoint.methodId) &&
((methodArgs != null) ?
methodArgs.equals(breakpoint.methodArgs)
: methodArgs == breakpoint.methodArgs) &&
refSpec.equals(breakpoint.refSpec) &&
(lineNumber == breakpoint.lineNumber);
} else {
return false;
}
}
@Override
String errorMessageFor(Exception e) {
if (e instanceof AmbiguousMethodException) {
return (MessageOutput.format("Method is overloaded; specify arguments",
methodName()));
/*
* TO DO: list the methods here
*/
} else if (e instanceof NoSuchMethodException) {
return (MessageOutput.format("No method in",
new Object [] {methodName(),
refSpec.toString()}));
} else if (e instanceof AbsentInformationException) {
return (MessageOutput.format("No linenumber information for",
refSpec.toString()));
} else if (e instanceof LineNotFoundException) {
return (MessageOutput.format("No code at line",
new Object [] {new Long (lineNumber()),
refSpec.toString()}));
} else if (e instanceof InvalidTypeException) {
return (MessageOutput.format("Breakpoints can be located only in classes.",
refSpec.toString()));
} else {
return super.errorMessageFor( e);
}
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer(refSpec.toString());
if (isMethodBreakpoint()) {
buffer.append('.');
buffer.append(methodId);
if (methodArgs != null) {
boolean first = true;
buffer.append('(');
for (String arg : methodArgs) {
if (!first) {
buffer.append(',');
}
buffer.append(arg);
first = false;
}
buffer.append(")");
}
} else {
buffer.append(':');
buffer.append(lineNumber);
}
return MessageOutput.format("breakpoint", buffer.toString());
}
private Location location(ReferenceType refType) throws
AmbiguousMethodException,
AbsentInformationException,
NoSuchMethodException,
LineNotFoundException {
Location location = null;
if (isMethodBreakpoint()) {
Method method = findMatchingMethod(refType);
location = method.location();
} else {
// let AbsentInformationException be thrown
List<Location> locs = refType.locationsOfLine(lineNumber());
if (locs.size() == 0) {
throw new LineNotFoundException();
}
// TO DO: handle multiple locations
location = locs.get(0);
if (location.method() == null) {
throw new LineNotFoundException();
}
}
return location;
}
private boolean isValidMethodName(String s) {
return isJavaIdentifier(s) ||
s.equals("<init>") ||
s.equals("<clinit>");
}
/*
* Compare a method's argument types with a Vector of type names.
* Return true if each argument type has a name identical to the
* corresponding string in the vector (allowing for varars)
* and if the number of arguments in the method matches the
* number of names passed
*/
private boolean compareArgTypes(Method method, List<String> nameList) {
List<String> argTypeNames = method.argumentTypeNames();
// If argument counts differ, we can stop here
if (argTypeNames.size() != nameList.size()) {
return false;
}
// Compare each argument type's name
int nTypes = argTypeNames.size();
for (int i = 0; i < nTypes; ++i) {
String comp1 = argTypeNames.get(i);
String comp2 = nameList.get(i);
if (! comp1.equals(comp2)) {
/*
* We have to handle varargs. EG, the
* method's last arg type is xxx[]
* while the nameList contains xxx...
* Note that the nameList can also contain
* xxx[] in which case we don't get here.
*/
if (i != nTypes - 1 ||
!method.isVarArgs() ||
!comp2.endsWith("...")) {
return false;
}
/*
* The last types differ, it is a varargs
* method and the nameList item is varargs.
* We just have to compare the type names, eg,
* make sure we don't have xxx[] for the method
* arg type and yyy... for the nameList item.
*/
int comp1Length = comp1.length();
if (comp1Length + 1 != comp2.length()) {
// The type names are different lengths
return false;
}
// We know the two type names are the same length
if (!comp1.regionMatches(0, comp2, 0, comp1Length - 2)) {
return false;
}
// We do have xxx[] and xxx... as the last param type
return true;
}
}
return true;
}
/*
* Remove unneeded spaces and expand class names to fully
* qualified names, if necessary and possible.
*/
private String normalizeArgTypeName(String name) {
/*
* Separate the type name from any array modifiers,
* stripping whitespace after the name ends
*/
int i = 0;
StringBuffer typePart = new StringBuffer();
StringBuffer arrayPart = new StringBuffer();
name = name.trim();
int nameLength = name.length();
/*
* For varargs, there can be spaces before the ... but not
* within the ... So, we will just ignore the ...
* while stripping blanks.
*/
boolean isVarArgs = name.endsWith("...");
if (isVarArgs) {
nameLength -= 3;
}
while (i < nameLength) {
char c = name.charAt(i);
if (Character.isWhitespace(c) || c == '[') {
break; // name is complete
}
typePart.append(c);
i++;
}
while (i < nameLength) {
char c = name.charAt(i);
if ( (c == '[') || (c == ']')) {
arrayPart.append(c);
} else if (!Character.isWhitespace(c)) {
throw new IllegalArgumentException
(MessageOutput.format("Invalid argument type name"));
}
i++;
}
name = typePart.toString();
/*
* When there's no sign of a package name already, try to expand the
* the name to a fully qualified class name
*/
if ((name.indexOf('.') == -1) || name.startsWith("*.")) {
try {
ReferenceType argClass = Env.getReferenceTypeFromToken(name);
if (argClass != null) {
name = argClass.name();
}
} catch (IllegalArgumentException e) {
// We'll try the name as is
}
}
name += arrayPart.toString();
if (isVarArgs) {
name += "...";
}
return name;
}
/*
* Attempt an unambiguous match of the method name and
* argument specification to a method. If no arguments
* are specified, the method must not be overloaded.
* Otherwise, the argument types much match exactly
*/
private Method findMatchingMethod(ReferenceType refType)
throws AmbiguousMethodException,
NoSuchMethodException {
// Normalize the argument string once before looping below.
List<String> argTypeNames = null;
if (methodArgs() != null) {
argTypeNames = new ArrayList<String>(methodArgs().size());
for (String name : methodArgs()) {
name = normalizeArgTypeName(name);
argTypeNames.add(name);
}
}
// Check each method in the class for matches
Method firstMatch = null; // first method with matching name
Method exactMatch = null; // (only) method with same name & sig
int matchCount = 0; // > 1 implies overload
for (Method candidate : refType.methods()) {
if (candidate.name().equals(methodName())) {
matchCount++;
// Remember the first match in case it is the only one
if (matchCount == 1) {
firstMatch = candidate;
}
// If argument types were specified, check against candidate
if ((argTypeNames != null)
&& compareArgTypes(candidate, argTypeNames) == true) {
exactMatch = candidate;
break;
}
}
}
// Determine method for breakpoint
Method method = null;
if (exactMatch != null) {
// Name and signature match
method = exactMatch;
} else if ((argTypeNames == null) && (matchCount > 0)) {
// At least one name matched and no arg types were specified
if (matchCount == 1) {
method = firstMatch; // Only one match; safe to use it
} else {
throw new AmbiguousMethodException();
}
} else {
throw new NoSuchMethodException(methodName());
}
return method;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,331 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.StepRequest;
import com.sun.jdi.request.MethodEntryRequest;
import com.sun.jdi.request.MethodExitRequest;
import java.util.*;
import java.io.*;
class Env {
static EventRequestSpecList specList = new EventRequestSpecList();
private static VMConnection connection;
private static SourceMapper sourceMapper = new SourceMapper("");
private static List<String> excludes;
private static final int SOURCE_CACHE_SIZE = 5;
private static List<SourceCode> sourceCache = new LinkedList<SourceCode>();
private static HashMap<String, Value> savedValues = new HashMap<String, Value>();
private static Method atExitMethod;
static void init(String connectSpec, boolean openNow, int flags) {
connection = new VMConnection(connectSpec, flags);
if (!connection.isLaunch() || openNow) {
connection.open();
}
}
static VMConnection connection() {
return connection;
}
static VirtualMachine vm() {
return connection.vm();
}
static void shutdown() {
shutdown(null);
}
static void shutdown(String message) {
if (connection != null) {
try {
connection.disposeVM();
} catch (VMDisconnectedException e) {
// Shutting down after the VM has gone away. This is
// not an error, and we just ignore it.
}
}
if (message != null) {
MessageOutput.lnprint(message);
MessageOutput.println();
}
System.exit(0);
}
static void setSourcePath(String srcPath) {
sourceMapper = new SourceMapper(srcPath);
sourceCache.clear();
}
static void setSourcePath(List<String> srcList) {
sourceMapper = new SourceMapper(srcList);
sourceCache.clear();
}
static String getSourcePath() {
return sourceMapper.getSourcePath();
}
static private List<String> excludes() {
if (excludes == null) {
setExcludes("java.*, javax.*, sun.*, com.sun.*");
}
return excludes;
}
static String excludesString() {
StringBuffer buffer = new StringBuffer();
for (String pattern : excludes()) {
buffer.append(pattern);
buffer.append(",");
}
return buffer.toString();
}
static void addExcludes(StepRequest request) {
for (String pattern : excludes()) {
request.addClassExclusionFilter(pattern);
}
}
static void addExcludes(MethodEntryRequest request) {
for (String pattern : excludes()) {
request.addClassExclusionFilter(pattern);
}
}
static void addExcludes(MethodExitRequest request) {
for (String pattern : excludes()) {
request.addClassExclusionFilter(pattern);
}
}
static void setExcludes(String excludeString) {
StringTokenizer t = new StringTokenizer(excludeString, " ,;");
List<String> list = new ArrayList<String>();
while (t.hasMoreTokens()) {
list.add(t.nextToken());
}
excludes = list;
}
static Method atExitMethod() {
return atExitMethod;
}
static void setAtExitMethod(Method mmm) {
atExitMethod = mmm;
}
/**
* Return a Reader cooresponding to the source of this location.
* Return null if not available.
* Note: returned reader must be closed.
*/
static BufferedReader sourceReader(Location location) {
return sourceMapper.sourceReader(location);
}
static synchronized String sourceLine(Location location, int lineNumber)
throws IOException {
if (lineNumber == -1) {
throw new IllegalArgumentException();
}
try {
String fileName = location.sourceName();
Iterator<SourceCode> iter = sourceCache.iterator();
SourceCode code = null;
while (iter.hasNext()) {
SourceCode candidate = iter.next();
if (candidate.fileName().equals(fileName)) {
code = candidate;
iter.remove();
break;
}
}
if (code == null) {
BufferedReader reader = sourceReader(location);
if (reader == null) {
throw new FileNotFoundException(fileName);
}
code = new SourceCode(fileName, reader);
if (sourceCache.size() == SOURCE_CACHE_SIZE) {
sourceCache.remove(sourceCache.size() - 1);
}
}
sourceCache.add(0, code);
return code.sourceLine(lineNumber);
} catch (AbsentInformationException e) {
throw new IllegalArgumentException();
}
}
/** Return a description of an object. */
static String description(ObjectReference ref) {
ReferenceType clazz = ref.referenceType();
long id = ref.uniqueID();
if (clazz == null) {
return toHex(id);
} else {
return MessageOutput.format("object description and hex id",
new Object [] {clazz.name(),
toHex(id)});
}
}
/** Convert a long to a hexadecimal string. */
static String toHex(long n) {
char s1[] = new char[16];
char s2[] = new char[18];
/* Store digits in reverse order. */
int i = 0;
do {
long d = n & 0xf;
s1[i++] = (char)((d < 10) ? ('0' + d) : ('a' + d - 10));
} while ((n >>>= 4) > 0);
/* Now reverse the array. */
s2[0] = '0';
s2[1] = 'x';
int j = 2;
while (--i >= 0) {
s2[j++] = s1[i];
}
return new String(s2, 0, j);
}
/** Convert hexadecimal strings to longs. */
static long fromHex(String hexStr) {
String str = hexStr.startsWith("0x") ?
hexStr.substring(2).toLowerCase() : hexStr.toLowerCase();
if (hexStr.length() == 0) {
throw new NumberFormatException();
}
long ret = 0;
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i);
if (c >= '0' && c <= '9') {
ret = (ret * 16) + (c - '0');
} else if (c >= 'a' && c <= 'f') {
ret = (ret * 16) + (c - 'a' + 10);
} else {
throw new NumberFormatException();
}
}
return ret;
}
static ReferenceType getReferenceTypeFromToken(String idToken) {
ReferenceType cls = null;
if (Character.isDigit(idToken.charAt(0))) {
cls = null;
} else if (idToken.startsWith("*.")) {
// This notation saves typing by letting the user omit leading
// package names. The first
// loaded class whose name matches this limited regular
// expression is selected.
idToken = idToken.substring(1);
for (ReferenceType type : Env.vm().allClasses()) {
if (type.name().endsWith(idToken)) {
cls = type;
break;
}
}
} else {
// It's a class name
List<ReferenceType> classes = Env.vm().classesByName(idToken);
if (classes.size() > 0) {
// TO DO: handle multiples
cls = classes.get(0);
}
}
return cls;
}
static Set<String> getSaveKeys() {
return savedValues.keySet();
}
static Value getSavedValue(String key) {
return savedValues.get(key);
}
static void setSavedValue(String key, Value value) {
savedValues.put(key, value);
}
static class SourceCode {
private String fileName;
private List<String> sourceLines = new ArrayList<String>();
SourceCode(String fileName, BufferedReader reader) throws IOException {
this.fileName = fileName;
try {
String line = reader.readLine();
while (line != null) {
sourceLines.add(line);
line = reader.readLine();
}
} finally {
reader.close();
}
}
String fileName() {
return fileName;
}
String sourceLine(int number) {
int index = number - 1; // list is 0-indexed
if (index >= sourceLines.size()) {
return null;
} else {
return sourceLines.get(index);
}
}
}
}

View File

@@ -0,0 +1,290 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.event.*;
import com.sun.jdi.request.EventRequest;
public class EventHandler implements Runnable {
EventNotifier notifier;
Thread thread;
volatile boolean connected = true;
boolean completed = false;
String shutdownMessageKey;
boolean stopOnVMStart;
EventHandler(EventNotifier notifier, boolean stopOnVMStart) {
this.notifier = notifier;
this.stopOnVMStart = stopOnVMStart;
this.thread = new Thread(this, "event-handler");
this.thread.start();
}
synchronized void shutdown() {
connected = false; // force run() loop termination
thread.interrupt();
while (!completed) {
try {wait();} catch (InterruptedException exc) {}
}
}
@Override
public void run() {
EventQueue queue = Env.vm().eventQueue();
while (connected) {
try {
EventSet eventSet = queue.remove();
boolean resumeStoppedApp = false;
EventIterator it = eventSet.eventIterator();
while (it.hasNext()) {
resumeStoppedApp |= !handleEvent(it.nextEvent());
}
if (resumeStoppedApp) {
eventSet.resume();
} else if (eventSet.suspendPolicy() == EventRequest.SUSPEND_ALL) {
setCurrentThread(eventSet);
notifier.vmInterrupted();
}
} catch (InterruptedException exc) {
// Do nothing. Any changes will be seen at top of loop.
} catch (VMDisconnectedException discExc) {
handleDisconnectedException();
break;
}
}
synchronized (this) {
completed = true;
notifyAll();
}
}
private boolean handleEvent(Event event) {
notifier.receivedEvent(event);
if (event instanceof ExceptionEvent) {
return exceptionEvent(event);
} else if (event instanceof BreakpointEvent) {
return breakpointEvent(event);
} else if (event instanceof WatchpointEvent) {
return fieldWatchEvent(event);
} else if (event instanceof StepEvent) {
return stepEvent(event);
} else if (event instanceof MethodEntryEvent) {
return methodEntryEvent(event);
} else if (event instanceof MethodExitEvent) {
return methodExitEvent(event);
} else if (event instanceof ClassPrepareEvent) {
return classPrepareEvent(event);
} else if (event instanceof ClassUnloadEvent) {
return classUnloadEvent(event);
} else if (event instanceof ThreadStartEvent) {
return threadStartEvent(event);
} else if (event instanceof ThreadDeathEvent) {
return threadDeathEvent(event);
} else if (event instanceof VMStartEvent) {
return vmStartEvent(event);
} else {
return handleExitEvent(event);
}
}
private boolean vmDied = false;
private boolean handleExitEvent(Event event) {
if (event instanceof VMDeathEvent) {
vmDied = true;
return vmDeathEvent(event);
} else if (event instanceof VMDisconnectEvent) {
connected = false;
if (!vmDied) {
vmDisconnectEvent(event);
}
/*
* Inform jdb command line processor that jdb is being shutdown. JDK-8154144.
*/
((TTY)notifier).setShuttingDown(true);
Env.shutdown(shutdownMessageKey);
return false;
} else {
throw new InternalError(MessageOutput.format("Unexpected event type",
new Object[] {event.getClass()}));
}
}
synchronized void handleDisconnectedException() {
/*
* A VMDisconnectedException has happened while dealing with
* another event. We need to flush the event queue, dealing only
* with exit events (VMDeath, VMDisconnect) so that we terminate
* correctly.
*/
EventQueue queue = Env.vm().eventQueue();
while (connected) {
try {
EventSet eventSet = queue.remove();
EventIterator iter = eventSet.eventIterator();
while (iter.hasNext()) {
handleExitEvent(iter.next());
}
} catch (InterruptedException exc) {
// ignore
} catch (InternalError exc) {
// ignore
}
}
}
private ThreadReference eventThread(Event event) {
if (event instanceof ClassPrepareEvent) {
return ((ClassPrepareEvent)event).thread();
} else if (event instanceof LocatableEvent) {
return ((LocatableEvent)event).thread();
} else if (event instanceof ThreadStartEvent) {
return ((ThreadStartEvent)event).thread();
} else if (event instanceof ThreadDeathEvent) {
return ((ThreadDeathEvent)event).thread();
} else if (event instanceof VMStartEvent) {
return ((VMStartEvent)event).thread();
} else {
return null;
}
}
private void setCurrentThread(EventSet set) {
ThreadReference thread;
if (set.size() > 0) {
/*
* If any event in the set has a thread associated with it,
* they all will, so just grab the first one.
*/
Event event = set.iterator().next(); // Is there a better way?
thread = eventThread(event);
} else {
thread = null;
}
setCurrentThread(thread);
}
private void setCurrentThread(ThreadReference thread) {
ThreadInfo.invalidateAll();
ThreadInfo.setCurrentThread(thread);
}
private boolean vmStartEvent(Event event) {
VMStartEvent se = (VMStartEvent)event;
notifier.vmStartEvent(se);
return stopOnVMStart;
}
private boolean breakpointEvent(Event event) {
BreakpointEvent be = (BreakpointEvent)event;
notifier.breakpointEvent(be);
return true;
}
private boolean methodEntryEvent(Event event) {
MethodEntryEvent me = (MethodEntryEvent)event;
notifier.methodEntryEvent(me);
return true;
}
private boolean methodExitEvent(Event event) {
MethodExitEvent me = (MethodExitEvent)event;
return notifier.methodExitEvent(me);
}
private boolean fieldWatchEvent(Event event) {
WatchpointEvent fwe = (WatchpointEvent)event;
notifier.fieldWatchEvent(fwe);
return true;
}
private boolean stepEvent(Event event) {
StepEvent se = (StepEvent)event;
notifier.stepEvent(se);
return true;
}
private boolean classPrepareEvent(Event event) {
ClassPrepareEvent cle = (ClassPrepareEvent)event;
notifier.classPrepareEvent(cle);
if (!Env.specList.resolve(cle)) {
MessageOutput.lnprint("Stopping due to deferred breakpoint errors.");
return true;
} else {
return false;
}
}
private boolean classUnloadEvent(Event event) {
ClassUnloadEvent cue = (ClassUnloadEvent)event;
notifier.classUnloadEvent(cue);
return false;
}
private boolean exceptionEvent(Event event) {
ExceptionEvent ee = (ExceptionEvent)event;
notifier.exceptionEvent(ee);
return true;
}
private boolean threadDeathEvent(Event event) {
ThreadDeathEvent tee = (ThreadDeathEvent)event;
ThreadInfo.removeThread(tee.thread());
return false;
}
private boolean threadStartEvent(Event event) {
ThreadStartEvent tse = (ThreadStartEvent)event;
ThreadInfo.addThread(tse.thread());
notifier.threadStartEvent(tse);
return false;
}
public boolean vmDeathEvent(Event event) {
shutdownMessageKey = "The application exited";
notifier.vmDeathEvent((VMDeathEvent)event);
return false;
}
public boolean vmDisconnectEvent(Event event) {
shutdownMessageKey = "The application has been disconnected";
notifier.vmDisconnectEvent((VMDisconnectEvent)event);
return false;
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.event.*;
interface EventNotifier {
void vmStartEvent(VMStartEvent e);
void vmDeathEvent(VMDeathEvent e);
void vmDisconnectEvent(VMDisconnectEvent e);
void threadStartEvent(ThreadStartEvent e);
void threadDeathEvent(ThreadDeathEvent e);
void classPrepareEvent(ClassPrepareEvent e);
void classUnloadEvent(ClassUnloadEvent e);
void breakpointEvent(BreakpointEvent e);
void fieldWatchEvent(WatchpointEvent e);
void stepEvent(StepEvent e);
void exceptionEvent(ExceptionEvent e);
void methodEntryEvent(MethodEntryEvent e);
boolean methodExitEvent(MethodExitEvent e);
void vmInterrupted();
void receivedEvent(Event event);
}

View File

@@ -0,0 +1,219 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.ExceptionRequest;
import com.sun.jdi.request.ClassPrepareRequest;
import com.sun.jdi.event.ClassPrepareEvent;
import java.util.ArrayList;
abstract class EventRequestSpec {
final ReferenceTypeSpec refSpec;
int suspendPolicy = EventRequest.SUSPEND_ALL;
EventRequest resolved = null;
ClassPrepareRequest prepareRequest = null;
EventRequestSpec(ReferenceTypeSpec refSpec) {
this.refSpec = refSpec;
}
/**
* The 'refType' is known to match, return the EventRequest.
*/
abstract EventRequest resolveEventRequest(ReferenceType refType)
throws Exception;
/**
* @return If this EventRequestSpec matches the 'refType'
* return the cooresponding EventRequest. Otherwise
* return null.
*/
synchronized EventRequest resolve(ClassPrepareEvent event) throws Exception {
if ((resolved == null) &&
(prepareRequest != null) &&
prepareRequest.equals(event.request())) {
resolved = resolveEventRequest(event.referenceType());
prepareRequest.disable();
Env.vm().eventRequestManager().deleteEventRequest(prepareRequest);
prepareRequest = null;
if (refSpec instanceof PatternReferenceTypeSpec) {
PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec;
if (! prs.isUnique()){
/*
* Class pattern event requests are never
* considered "resolved", since future class loads
* might also match.
* Create and enable a new ClassPrepareRequest to
* keep trying to resolve.
*/
resolved = null;
prepareRequest = refSpec.createPrepareRequest();
prepareRequest.enable();
}
}
}
return resolved;
}
synchronized void remove() {
if (isResolved()) {
Env.vm().eventRequestManager().deleteEventRequest(resolved());
}
if (refSpec instanceof PatternReferenceTypeSpec) {
PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec;
if (! prs.isUnique()){
/*
* This is a class pattern. Track down and delete
* all EventRequests matching this spec.
* Note: Class patterns apply only to ExceptionRequests,
* so that is all we need to examine.
*/
ArrayList<ExceptionRequest> deleteList = new ArrayList<ExceptionRequest>();
for (ExceptionRequest er :
Env.vm().eventRequestManager().exceptionRequests()) {
if (prs.matches(er.exception())) {
deleteList.add (er);
}
}
Env.vm().eventRequestManager().deleteEventRequests(deleteList);
}
}
}
private EventRequest resolveAgainstPreparedClasses() throws Exception {
for (ReferenceType refType : Env.vm().allClasses()) {
if (refType.isPrepared() && refSpec.matches(refType)) {
resolved = resolveEventRequest(refType);
}
}
return resolved;
}
synchronized EventRequest resolveEagerly() throws Exception {
try {
if (resolved == null) {
/*
* Not resolved. Schedule a prepare request so we
* can resolve later.
*/
prepareRequest = refSpec.createPrepareRequest();
prepareRequest.enable();
// Try to resolve in case the class is already loaded.
resolveAgainstPreparedClasses();
if (resolved != null) {
prepareRequest.disable();
Env.vm().eventRequestManager().deleteEventRequest(prepareRequest);
prepareRequest = null;
}
}
if (refSpec instanceof PatternReferenceTypeSpec) {
PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec;
if (! prs.isUnique()){
/*
* Class pattern event requests are never
* considered "resolved", since future class loads
* might also match. Create a new
* ClassPrepareRequest if necessary and keep
* trying to resolve.
*/
resolved = null;
if (prepareRequest == null) {
prepareRequest = refSpec.createPrepareRequest();
prepareRequest.enable();
}
}
}
} catch (VMNotConnectedException e) {
// Do nothing. Another resolve will be attempted when the
// VM is started.
}
return resolved;
}
/**
* @return the eventRequest this spec has been resolved to,
* null if so far unresolved.
*/
EventRequest resolved() {
return resolved;
}
/**
* @return true if this spec has been resolved.
*/
boolean isResolved() {
return resolved != null;
}
protected boolean isJavaIdentifier(String s) {
if (s.length() == 0) {
return false;
}
int cp = s.codePointAt(0);
if (! Character.isJavaIdentifierStart(cp)) {
return false;
}
for (int i = Character.charCount(cp); i < s.length(); i += Character.charCount(cp)) {
cp = s.codePointAt(i);
if (! Character.isJavaIdentifierPart(cp)) {
return false;
}
}
return true;
}
String errorMessageFor(Exception e) {
if (e instanceof IllegalArgumentException) {
return (MessageOutput.format("Invalid command syntax"));
} else if (e instanceof RuntimeException) {
// A runtime exception that we were not expecting
throw (RuntimeException)e;
} else {
return (MessageOutput.format("Internal error; unable to set",
this.refSpec.toString()));
}
}
}

View File

@@ -0,0 +1,175 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.event.ClassPrepareEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class EventRequestSpecList {
private static final int statusResolved = 1;
private static final int statusUnresolved = 2;
private static final int statusError = 3;
// all specs
private List<EventRequestSpec> eventRequestSpecs = Collections.synchronizedList(
new ArrayList<EventRequestSpec>());
EventRequestSpecList() {
}
/**
* Resolve all deferred eventRequests waiting for 'refType'.
* @return true if it completes successfully, false on error.
*/
boolean resolve(ClassPrepareEvent event) {
boolean failure = false;
synchronized(eventRequestSpecs) {
for (EventRequestSpec spec : eventRequestSpecs) {
if (!spec.isResolved()) {
try {
EventRequest eventRequest = spec.resolve(event);
if (eventRequest != null) {
MessageOutput.println("Set deferred", spec.toString());
}
} catch (Exception e) {
MessageOutput.println("Unable to set deferred",
new Object [] {spec.toString(),
spec.errorMessageFor(e)});
failure = true;
}
}
}
}
return !failure;
}
void resolveAll() {
for (EventRequestSpec spec : eventRequestSpecs) {
try {
EventRequest eventRequest = spec.resolveEagerly();
if (eventRequest != null) {
MessageOutput.println("Set deferred", spec.toString());
}
} catch (Exception e) {
}
}
}
boolean addEagerlyResolve(EventRequestSpec spec) {
try {
eventRequestSpecs.add(spec);
EventRequest eventRequest = spec.resolveEagerly();
if (eventRequest != null) {
MessageOutput.println("Set", spec.toString());
}
return true;
} catch (Exception exc) {
MessageOutput.println("Unable to set",
new Object [] {spec.toString(),
spec.errorMessageFor(exc)});
return false;
}
}
BreakpointSpec createBreakpoint(String classPattern, int line)
throws ClassNotFoundException {
ReferenceTypeSpec refSpec =
new PatternReferenceTypeSpec(classPattern);
return new BreakpointSpec(refSpec, line);
}
BreakpointSpec createBreakpoint(String classPattern,
String methodId,
List<String> methodArgs)
throws MalformedMemberNameException,
ClassNotFoundException {
ReferenceTypeSpec refSpec =
new PatternReferenceTypeSpec(classPattern);
return new BreakpointSpec(refSpec, methodId, methodArgs);
}
EventRequestSpec createExceptionCatch(String classPattern,
boolean notifyCaught,
boolean notifyUncaught)
throws ClassNotFoundException {
ReferenceTypeSpec refSpec =
new PatternReferenceTypeSpec(classPattern);
return new ExceptionSpec(refSpec, notifyCaught, notifyUncaught);
}
WatchpointSpec createAccessWatchpoint(String classPattern,
String fieldId)
throws MalformedMemberNameException,
ClassNotFoundException {
ReferenceTypeSpec refSpec =
new PatternReferenceTypeSpec(classPattern);
return new AccessWatchpointSpec(refSpec, fieldId);
}
WatchpointSpec createModificationWatchpoint(String classPattern,
String fieldId)
throws MalformedMemberNameException,
ClassNotFoundException {
ReferenceTypeSpec refSpec =
new PatternReferenceTypeSpec(classPattern);
return new ModificationWatchpointSpec(refSpec, fieldId);
}
boolean delete(EventRequestSpec proto) {
synchronized (eventRequestSpecs) {
int inx = eventRequestSpecs.indexOf(proto);
if (inx != -1) {
EventRequestSpec spec = eventRequestSpecs.get(inx);
spec.remove();
eventRequestSpecs.remove(inx);
return true;
} else {
return false;
}
}
}
List<EventRequestSpec> eventRequestSpecs() {
// We need to make a copy to avoid synchronization problems
synchronized (eventRequestSpecs) {
return new ArrayList<EventRequestSpec>(eventRequestSpecs);
}
}
}

View File

@@ -0,0 +1,116 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.request.*;
class ExceptionSpec extends EventRequestSpec {
private boolean notifyCaught;
private boolean notifyUncaught;
private ExceptionSpec(ReferenceTypeSpec refSpec) {
this(refSpec, true, true);
}
ExceptionSpec(ReferenceTypeSpec refSpec,
boolean notifyCaught,
boolean notifyUncaught) {
super(refSpec);
this.notifyCaught = notifyCaught;
this.notifyUncaught = notifyUncaught;
}
/**
* The 'refType' is known to match, return the EventRequest.
*/
@Override
EventRequest resolveEventRequest(ReferenceType refType) {
EventRequestManager em = refType.virtualMachine().eventRequestManager();
ExceptionRequest excReq = em.createExceptionRequest(refType,
notifyCaught,
notifyUncaught);
excReq.enable();
return excReq;
}
public boolean notifyCaught() {
return notifyCaught;
}
public boolean notifyUncaught() {
return notifyUncaught;
}
@Override
public int hashCode() {
//Reference: Effective Java[tm] (Bloch, 2001), Item 8
int result = 17;
result = (37 * result) + (notifyCaught() ? 0: 1);
result = (37 * result) + (notifyUncaught() ? 0: 1);
result = (37 * result) + refSpec.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ExceptionSpec) {
ExceptionSpec es = (ExceptionSpec)obj;
if (refSpec.equals(es.refSpec) &&
(this.notifyCaught() == es.notifyCaught()) &&
(this.notifyUncaught() == es.notifyUncaught())) {
return true;
}
}
return false;
}
@Override
public String toString() {
String s;
if (notifyCaught && !notifyUncaught) {
s = MessageOutput.format("exceptionSpec caught",
refSpec.toString());
} else if (notifyUncaught && !notifyCaught) {
s = MessageOutput.format("exceptionSpec uncaught",
refSpec.toString());
} else {
s = MessageOutput.format("exceptionSpec all",
refSpec.toString());
}
return s;
}
}

View File

@@ -0,0 +1,50 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
public class LineNotFoundException extends Exception
{
private static final long serialVersionUID = 3748297722519448995L;
public LineNotFoundException()
{
super();
}
public LineNotFoundException(String s)
{
super(s);
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
class MalformedMemberNameException extends Exception {
private static final long serialVersionUID = 7759071468833196630L;
public MalformedMemberNameException() {
super();
}
public MalformedMemberNameException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,205 @@
/*
* Copyright (c) 2001, 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import java.util.*;
import java.text.MessageFormat;
/**
* Internationalization (i18n) convenience methods for jdb.
*
* All program output should flow through these methods, and this is
* the only class that should be printing directly or otherwise
* accessing System.[out,err].
*
* @bug 4348376
* @author Tim Bell
*/
public class MessageOutput {
/**
* The resource bundle containing localizable message content.
* This is loaded by TTY.main() at start-up
*/
static ResourceBundle textResources;
/** Our message formatter. Allocated once, used many times */
private static MessageFormat messageFormat;
/**
* Fatal shutdown notification. This is sent to System.err
* instead of System.out
*/
static void fatalError(String messageKey) {
System.err.println();
System.err.println(format("Fatal error"));
System.err.println(format(messageKey));
Env.shutdown();
}
/**
* "Format" a string by doing a simple key lookup.
*/
static String format(String key) {
return (textResources.getString(key));
}
/**
* Fetch and format a message with one string argument.
* This is the most common usage.
*/
static String format(String key, String argument) {
return format(key, new Object [] {argument});
}
/**
* Fetch a string by key lookup and format in the arguments.
*/
static synchronized String format(String key, Object [] arguments) {
if (messageFormat == null) {
messageFormat = new MessageFormat (textResources.getString(key));
} else {
messageFormat.applyPattern (textResources.getString(key));
}
return (messageFormat.format (arguments));
}
/**
* Print directly to System.out.
* Every rule has a few exceptions.
* The exceptions to "must use the MessageOutput formatters" are:
* VMConnection.dumpStream()
* TTY.monitorCommand()
* TTY.TTY() (for the '!!' command only)
* Commands.java (multiple locations)
* These are the only sites that should be calling this
* method.
*/
static void printDirectln(String line) {
System.out.println(line);
}
static void printDirect(String line) {
System.out.print(line);
}
static void printDirect(char c) {
System.out.print(c);
}
/**
* Print a newline.
* Use this instead of '\n'
*/
static void println() {
System.out.println();
}
/**
* Format and print a simple string.
*/
static void print(String key) {
System.out.print(format(key));
}
/**
* Format and print a simple string.
*/
static void println(String key) {
System.out.println(format(key));
}
/**
* Fetch, format and print a message with one string argument.
* This is the most common usage.
*/
static void print(String key, String argument) {
System.out.print(format(key, argument));
}
static void println(String key, String argument) {
System.out.println(format(key, argument));
}
/**
* Fetch, format and print a message with an arbitrary
* number of message arguments.
*/
static void println(String key, Object [] arguments) {
System.out.println(format(key, arguments));
}
/**
* Print a newline, followed by the string.
*/
static void lnprint(String key) {
System.out.println();
System.out.print(textResources.getString(key));
}
static void lnprint(String key, String argument) {
System.out.println();
System.out.print(format(key, argument));
}
static void lnprint(String key, Object [] arguments) {
System.out.println();
System.out.print(format(key, arguments));
}
/**
* Print an exception message with a stack trace.
*/
static void printException(String key, Exception e) {
if (key != null) {
try {
println(key);
} catch (MissingResourceException mex) {
printDirectln(key);
}
}
System.out.flush();
e.printStackTrace();
}
static void printPrompt() {
ThreadInfo threadInfo = ThreadInfo.getCurrentThreadInfo();
if (threadInfo == null) {
System.out.print
(MessageOutput.format("jdb prompt with no current thread"));
} else {
System.out.print
(MessageOutput.format("jdb prompt thread name and current stack frame",
new Object [] {
threadInfo.getThread().name(),
new Integer (threadInfo.getCurrentFrameIndex() + 1)}));
}
System.out.flush();
}
}

View File

@@ -0,0 +1,67 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.EventRequest;
class ModificationWatchpointSpec extends WatchpointSpec {
ModificationWatchpointSpec(ReferenceTypeSpec refSpec, String fieldId)
throws MalformedMemberNameException {
super(refSpec, fieldId);
}
/**
* The 'refType' is known to match, return the EventRequest.
*/
@Override
EventRequest resolveEventRequest(ReferenceType refType)
throws NoSuchFieldException {
Field field = refType.fieldByName(fieldId);
EventRequestManager em = refType.virtualMachine().eventRequestManager();
EventRequest wp = em.createModificationWatchpointRequest(field);
wp.setSuspendPolicy(suspendPolicy);
wp.enable();
return wp;
}
@Override
public String toString() {
return MessageOutput.format("watch modification of",
new Object [] {refSpec.toString(),
fieldId});
}
}

View File

@@ -0,0 +1,145 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.ClassPrepareRequest;
import java.util.StringTokenizer;
class PatternReferenceTypeSpec implements ReferenceTypeSpec {
final String classId;
String stem;
PatternReferenceTypeSpec(String classId) throws ClassNotFoundException {
this.classId = classId;
stem = classId;
if (classId.startsWith("*")) {
stem = stem.substring(1);
} else if (classId.endsWith("*")) {
stem = stem.substring(0, classId.length() - 1);
}
checkClassName(stem);
}
/**
* Is this spec unique or is it a class pattern?
*/
public boolean isUnique() {
return classId.equals(stem);
}
/**
* Does the specified ReferenceType match this spec.
*/
@Override
public boolean matches(ReferenceType refType) {
if (classId.startsWith("*")) {
return refType.name().endsWith(stem);
} else if (classId.endsWith("*")) {
return refType.name().startsWith(stem);
} else {
return refType.name().equals(classId);
}
}
@Override
public ClassPrepareRequest createPrepareRequest() {
ClassPrepareRequest request =
Env.vm().eventRequestManager().createClassPrepareRequest();
request.addClassFilter(classId);
request.addCountFilter(1);
return request;
}
@Override
public int hashCode() {
return classId.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof PatternReferenceTypeSpec) {
PatternReferenceTypeSpec spec = (PatternReferenceTypeSpec)obj;
return classId.equals(spec.classId);
} else {
return false;
}
}
private void checkClassName(String className) throws ClassNotFoundException {
// Do stricter checking of class name validity on deferred
// because if the name is invalid, it will
// never match a future loaded class, and we'll be silent
// about it.
StringTokenizer tokenizer = new StringTokenizer(className, ".");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
// Each dot-separated piece must be a valid identifier
// and the first token can also be "*". (Note that
// numeric class ids are not permitted. They must
// match a loaded class.)
if (!isJavaIdentifier(token)) {
throw new ClassNotFoundException();
}
}
}
private boolean isJavaIdentifier(String s) {
if (s.length() == 0) {
return false;
}
int cp = s.codePointAt(0);
if (! Character.isJavaIdentifierStart(cp)) {
return false;
}
for (int i = Character.charCount(cp); i < s.length(); i += Character.charCount(cp)) {
cp = s.codePointAt(i);
if (! Character.isJavaIdentifierPart(cp)) {
return false;
}
}
return true;
}
@Override
public String toString() {
return classId;
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.request.ClassPrepareRequest;
interface ReferenceTypeSpec {
/**
* Does the specified ReferenceType match this spec.
*/
boolean matches(ReferenceType refType);
ClassPrepareRequest createPrepareRequest();
@Override
int hashCode();
@Override
boolean equals(Object obj);
}

View File

@@ -0,0 +1,147 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.Location;
import com.sun.jdi.AbsentInformationException;
import java.util.List;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.io.*;
class SourceMapper {
private final String[] dirs;
SourceMapper(List<String> sourcepath) {
/*
* sourcepath can arrive from the debugee as a List.
* (via PathSearchingVirtualMachine.classPath())
*/
List<String> dirList = new ArrayList<String>();
for (String element : sourcepath) {
//XXX remove .jar and .zip files; we want only directories on
//the source path. (Bug ID 4186582)
if ( ! (element.endsWith(".jar") ||
element.endsWith(".zip"))) {
dirList.add(element);
}
}
dirs = dirList.toArray(new String[0]);
}
SourceMapper(String sourcepath) {
/*
* sourcepath can also arrive from the command line
* as a String. (via "-sourcepath")
*
* Using File.pathSeparator as delimiter below is OK
* because we are on the same machine as the command
* line originiated.
*/
StringTokenizer st = new StringTokenizer(sourcepath,
File.pathSeparator);
List<String> dirList = new ArrayList<String>();
while (st.hasMoreTokens()) {
String s = st.nextToken();
//XXX remove .jar and .zip files; we want only directories on
//the source path. (Bug ID 4186582)
if ( ! (s.endsWith(".jar") ||
s.endsWith(".zip"))) {
dirList.add(s);
}
}
dirs = dirList.toArray(new String[0]);
}
/*
* Return the current sourcePath as a String.
*/
String getSourcePath() {
int i = 0;
StringBuffer sp;
if (dirs.length < 1) {
return ""; //The source path is empty.
} else {
sp = new StringBuffer(dirs[i++]);
}
for (; i < dirs.length; i++) {
sp.append(File.pathSeparator);
sp.append(dirs[i]);
}
return sp.toString();
}
/**
* Return a File cooresponding to the source of this location.
* Return null if not available.
*/
File sourceFile(Location loc) {
try {
String filename = loc.sourceName();
String refName = loc.declaringType().name();
int iDot = refName.lastIndexOf('.');
String pkgName = (iDot >= 0)? refName.substring(0, iDot+1) : "";
String full = pkgName.replace('.', File.separatorChar) + filename;
for (int i= 0; i < dirs.length; ++i) {
File path = new File(dirs[i], full);
if (path.exists()) {
return path;
}
}
return null;
} catch (AbsentInformationException e) {
return null;
}
}
/**
* Return a BufferedReader cooresponding to the source
* of this location.
* Return null if not available.
* Note: returned reader must be closed.
*/
BufferedReader sourceReader(Location loc) {
File sourceFile = sourceFile(loc);
if (sourceFile == null) {
return null;
}
try {
return new BufferedReader(new FileReader(sourceFile));
} catch(IOException exc) {
}
return null;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,465 @@
/*
* Copyright (c) 2001, 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
/**
* <p> This class represents the <code>ResourceBundle</code>
* for the following package(s):
*
* <ol>
* <li> com.sun.tools.example.debug.tty
* </ol>
*
*/
public class TTYResources extends java.util.ListResourceBundle {
/**
* Returns the contents of this <code>ResourceBundle</code>.
*
* <p>
*
* @return the contents of this <code>ResourceBundle</code>.
*/
@Override
public Object[][] getContents() {
Object[][] temp = new Object[][] {
// NOTE: The value strings in this file containing "{0}" are
// processed by the java.text.MessageFormat class. Any
// single quotes appearing in these strings need to be
// doubled up.
//
// LOCALIZE THIS
{"** classes list **", "** classes list **\n{0}"},
{"** fields list **", "** fields list **\n{0}"},
{"** methods list **", "** methods list **\n{0}"},
{"*** Reading commands from", "*** Reading commands from {0}"},
{"All threads resumed.", "All threads resumed."},
{"All threads suspended.", "All threads suspended."},
{"Argument is not defined for connector:", "Argument {0} is not defined for connector: {1}"},
{"Arguments match no method", "Arguments match no method"},
{"Array:", "Array: {0}"},
{"Array element is not a method", "Array element is not a method"},
{"Array index must be a integer type", "Array index must be a integer type"},
{"base directory:", "base directory: {0}"},
{"bootclasspath:", "bootclasspath: {0}"},
{"Breakpoint hit:", "Breakpoint hit: "},
{"breakpoint", "breakpoint {0}"},
{"Breakpoints set:", "Breakpoints set:"},
{"Breakpoints can be located only in classes.", "Breakpoints can be located only in classes. {0} is an interface or array."},
{"Can only trace", "Can only trace 'methods' or 'method exit' or 'method exits'"},
{"cannot redefine existing connection", "{0} cannot redefine existing connection"},
{"Cannot assign to a method invocation", "Cannot assign to a method invocation"},
{"Cannot specify command line with connector:", "Cannot specify command line with connector: {0}"},
{"Cannot specify target vm arguments with connector:", "Cannot specify target VM arguments with connector: {0}"},
{"Class containing field must be specified.", "Class containing field must be specified."},
{"Class:", "Class: {0}"},
{"Classic VM no longer supported.", "Classic VM no longer supported."},
{"classpath:", "classpath: {0}"},
{"colon mark", ":"},
{"colon space", ": "},
{"Command is not supported on the target VM", "Command ''{0}'' is not supported on the target VM"},
{"Command is not supported on a read-only VM connection", "Command ''{0}'' is not supported on a read-only VM connection"},
{"Command not valid until the VM is started with the run command", "Command ''{0}'' is not valid until the VM is started with the ''run'' command"},
{"Condition must be boolean", "Condition must be boolean"},
{"Connector and Transport name", " Connector: {0} Transport: {1}"},
{"Connector argument nodefault", " Argument: {0} (no default)"},
{"Connector argument default", " Argument: {0} Default value: {1}"},
{"Connector description", " description: {0}"},
{"Connector required argument nodefault", " Required Argument: {0} (no default)"},
{"Connector required argument default", " Required Argument: {0} Default value: {1}"},
{"Connectors available", "Available connectors are:"},
{"Constant is not a method", "Constant is not a method"},
{"Could not open:", "Could not open: {0}"},
{"Current method is native", "Current method is native"},
{"Current thread died. Execution continuing...", "Current thread {0} died. Execution continuing..."},
{"Current thread isnt suspended.", "Current thread isn't suspended."},
{"Current thread not set.", "Current thread not set."},
{"dbgtrace flag value must be an integer:", "dbgtrace flag value must be an integer: {0}"},
{"Deferring.", "Deferring {0}.\nIt will be set after the class is loaded."},
{"End of stack.", "End of stack."},
{"Error popping frame", "Error popping frame - {0}"},
{"Error reading file", "Error reading ''{0}'' - {1}"},
{"Error redefining class to file", "Error redefining {0} to {1} - {2}"},
{"exceptionSpec all", "all {0}"},
{"exceptionSpec caught", "caught {0}"},
{"exceptionSpec uncaught", "uncaught {0}"},
{"Exception in expression:", "Exception in expression: {0}"},
{"Exception occurred caught", "Exception occurred: {0} (to be caught at: {1})"},
{"Exception occurred uncaught", "Exception occurred: {0} (uncaught)"},
{"Exceptions caught:", "Break when these exceptions occur:"},
{"expr is null", "{0} = null"},
{"expr is value", "{0} = {1}"},
{"expr is value <collected>", " {0} = {1} <collected>"},
{"Expression cannot be void", "Expression cannot be void"},
{"Expression must evaluate to an object", "Expression must evaluate to an object"},
{"extends:", "extends: {0}"},
{"Failed reading output", "Failed reading output of child java interpreter."},
{"Fatal error", "Fatal error:"},
{"Field access encountered before after", "Field ({0}) is {1}, will be {2}: "},
{"Field access encountered", "Field ({0}) access encountered: "},
{"Field to unwatch not specified", "Field to unwatch not specified."},
{"Field to watch not specified", "Field to watch not specified."},
{"GC Disabled for", "GC Disabled for {0}:"},
{"GC Enabled for", "GC Enabled for {0}:"},
{"grouping begin character", "{"},
{"grouping end character", "}"},
{"Illegal Argument Exception", "Illegal Argument Exception"},
{"Illegal connector argument", "Illegal connector argument: {0}"},
{"implementor:", "implementor: {0}"},
{"implements:", "implements: {0}"},
{"Initializing progname", "Initializing {0} ..."},
{"Input stream closed.", "Input stream closed."},
{"Interface:", "Interface: {0}"},
{"Internal debugger error.", "Internal debugger error."},
{"Internal error: null ThreadInfo created", "Internal error: null ThreadInfo created"},
{"Internal error; unable to set", "Internal error; unable to set {0}"},
{"Internal exception during operation:", "Internal exception during operation:\n {0}"},
{"Internal exception:", "Internal exception:"},
{"Invalid argument type name", "Invalid argument type name"},
{"Invalid assignment syntax", "Invalid assignment syntax"},
{"Invalid command syntax", "Invalid command syntax"},
{"Invalid connect type", "Invalid connect type"},
{"Invalid consecutive invocations", "Invalid consecutive invocations"},
{"Invalid exception object", "Invalid exception object"},
{"Invalid method specification:", "Invalid method specification: {0}"},
{"Invalid option on class command", "Invalid option on class command"},
{"invalid option", "invalid option: {0}"},
{"Invalid thread status.", "Invalid thread status."},
{"Invalid transport name:", "Invalid transport name: {0}"},
{"I/O exception occurred:", "I/O Exception occurred: {0}"},
{"is an ambiguous method name in", "\"{0}\" is an ambiguous method name in \"{1}\""},
{"is an invalid line number for", "{0,number,integer} is an invalid line number for {1}"},
{"is not a valid class name", "\"{0}\" is not a valid class name."},
{"is not a valid field name", "\"{0}\" is not a valid field name."},
{"is not a valid id or class name", "\"{0}\" is not a valid id or class name."},
{"is not a valid line number or method name for", "\"{0}\" is not a valid line number or method name for class \"{1}\""},
{"is not a valid method name", "\"{0}\" is not a valid method name."},
{"is not a valid thread id", "\"{0}\" is not a valid thread id."},
{"is not a valid threadgroup name", "\"{0}\" is not a valid threadgroup name."},
{"jdb prompt with no current thread", "> "},
{"jdb prompt thread name and current stack frame", "{0}[{1,number,integer}] "},
{"killed", "{0} killed"},
{"killing thread:", "killing thread: {0}"},
{"Line number information not available for", "Source line numbers not available for this location."},
{"line number", ":{0,number,integer}"},
{"list field typename and name", "{0} {1}\n"},
{"list field typename and name inherited", "{0} {1} (inherited from {2})\n"},
{"list field typename and name hidden", "{0} {1} (hidden)\n"},
{"Listening at address:", "Listening at address: {0}"},
{"Local variable information not available.", "Local variable information not available. Compile with -g to generate variable information"},
{"Local variables:", "Local variables:"},
{"<location unavailable>", "<location unavailable>"},
{"location", "\"thread={0}\", {1}"},
{"locationString", "{0}.{1}(), line={2,number,integer} bci={3,number,integer}"},
{"Main class and arguments must be specified", "Main class and arguments must be specified"},
{"Method arguments:", "Method arguments:"},
{"Method entered:", "Method entered: "},
{"Method exited:", "Method exited"},
{"Method exitedValue:", "Method exited: return value = {0}, "},
{"Method is overloaded; specify arguments", "Method {0} is overloaded; specify arguments"},
{"minus version", "This is {0} version {1,number,integer}.{2,number,integer} (Java SE version {3})"},
{"Monitor information for thread", "Monitor information for thread {0}:"},
{"Monitor information for expr", "Monitor information for {0} ({1}):"},
{"More than one class named", "More than one class named: ''{0}''"},
{"native method", "native method"},
{"nested:", "nested: {0}"},
{"No attach address specified.", "No attach address specified."},
{"No breakpoints set.", "No breakpoints set."},
{"No class named", "No class named ''{0}''"},
{"No class specified.", "No class specified."},
{"No classpath specified.", "No classpath specified."},
{"No code at line", "No code at line {0,number,integer} in {1}"},
{"No connect specification.", "No connect specification."},
{"No connector named:", "No connector named: {0}"},
{"No current thread", "No current thread"},
{"No default thread specified:", "No default thread specified: use the \"thread\" command first."},
{"No exception object specified.", "No exception object specified."},
{"No exceptions caught.", "No exceptions caught."},
{"No expression specified.", "No expression specified."},
{"No field in", "No field {0} in {1}"},
{"No frames on the current call stack", "No frames on the current call stack"},
{"No linenumber information for", "No linenumber information for {0}. Try compiling with debugging on."},
{"No local variables", "No local variables"},
{"No method in", "No method {0} in {1}"},
{"No method specified.", "No method specified."},
{"No monitor numbered:", "No monitor numbered: {0}"},
{"No monitors owned", " No monitors owned"},
{"No object specified.", "No object specified."},
{"No objects specified.", "No objects specified."},
{"No save index specified.", "No save index specified."},
{"No saved values", "No saved values"},
{"No source information available for:", "No source information available for: {0}"},
{"No sourcedebugextension specified", "No SourceDebugExtension specified"},
{"No sourcepath specified.", "No sourcepath specified."},
{"No thread specified.", "No thread specified."},
{"No VM connected", "No VM connected"},
{"No waiters", " No waiters"},
{"not a class", "{0} is not a class"},
{"Not a monitor number:", "Not a monitor number: ''{0}''"},
{"not found (try the full name)", "{0} not found (try the full name)"},
{"Not found:", "Not found: {0}"},
{"not found", "{0} not found"},
{"Not owned", " Not owned"},
{"Not waiting for a monitor", " Not waiting for a monitor"},
{"Nothing suspended.", "Nothing suspended."},
{"object description and hex id", "({0}){1}"},
{"Operation is not supported on the target VM", "Operation is not supported on the target VM"},
{"operation not yet supported", "operation not yet supported"},
{"Owned by:", " Owned by: {0}, entry count: {1,number,integer}"},
{"Owned monitor:", " Owned monitor: {0}"},
{"Parse exception:", "Parse Exception: {0}"},
{"printbreakpointcommandusage", "Usage: {0} <class>:<line_number> or\n {1} <class>.<method_name>[(argument_type,...)]"},
{"Removed:", "Removed: {0}"},
{"Requested stack frame is no longer active:", "Requested stack frame is no longer active: {0,number,integer}"},
{"run <args> command is valid only with launched VMs", "'run <args>' command is valid only with launched VMs"},
{"run", "run {0}"},
{"saved", "{0} saved"},
{"Set deferred", "Set deferred {0}"},
{"Set", "Set {0}"},
{"Source file not found:", "Source file not found: {0}"},
{"source line number and line", "{0,number,integer} {1}"},
{"source line number current line and line", "{0,number,integer} => {1}"},
{"sourcedebugextension", "SourceDebugExtension -- {0}"},
{"Specify class and method", "Specify class and method"},
{"Specify classes to redefine", "Specify classes to redefine"},
{"Specify file name for class", "Specify file name for class {0}"},
{"stack frame dump with pc", " [{0,number,integer}] {1}.{2} ({3}), pc = {4}"},
{"stack frame dump", " [{0,number,integer}] {1}.{2} ({3})"},
{"Step completed:", "Step completed: "},
{"Stopping due to deferred breakpoint errors.", "Stopping due to deferred breakpoint errors.\n"},
{"subclass:", "subclass: {0}"},
{"subinterface:", "subinterface: {0}"},
{"tab", "\t{0}"},
{"Target VM failed to initialize.", "Target VM failed to initialize."},
{"The application exited", "The application exited"},
{"The application has been disconnected", "The application has been disconnected"},
{"The gc command is no longer necessary.", "The 'gc' command is no longer necessary.\n" +
"All objects are garbage collected as usual. Use 'enablegc' and 'disablegc'\n" +
"commands to control garbage collection of individual objects."},
{"The load command is no longer supported.", "The 'load' command is no longer supported."},
{"The memory command is no longer supported.", "The 'memory' command is no longer supported."},
{"The VM does not use paths", "The VM does not use paths"},
{"Thread is not running (no stack).", "Thread is not running (no stack)."},
{"Thread number not specified.", "Thread number not specified."},
{"Thread:", "{0}:"},
{"Thread Group:", "Group {0}:"},
{"Thread description name unknownStatus BP", " {0} {1} unknown (at breakpoint)"},
{"Thread description name unknownStatus", " {0} {1} unknown"},
{"Thread description name zombieStatus BP", " {0} {1} zombie (at breakpoint)"},
{"Thread description name zombieStatus", " {0} {1} zombie"},
{"Thread description name runningStatus BP", " {0} {1} running (at breakpoint)"},
{"Thread description name runningStatus", " {0} {1} running"},
{"Thread description name sleepingStatus BP", " {0} {1} sleeping (at breakpoint)"},
{"Thread description name sleepingStatus", " {0} {1} sleeping"},
{"Thread description name waitingStatus BP", " {0} {1} waiting in a monitor (at breakpoint)"},
{"Thread description name waitingStatus", " {0} {1} waiting in a monitor"},
{"Thread description name condWaitstatus BP", " {0} {1} cond. waiting (at breakpoint)"},
{"Thread description name condWaitstatus", " {0} {1} cond. waiting"},
{"Thread has been resumed", "Thread has been resumed"},
{"Thread not suspended", "Thread not suspended"},
{"thread group number description name", "{0,number,integer}. {1} {2}"},
{"Threadgroup name not specified.", "Threadgroup name not specified."},
{"Threads must be suspended", "Threads must be suspended"},
{"trace method exit in effect for", "trace method exit in effect for {0}"},
{"trace method exits in effect", "trace method exits in effect"},
{"trace methods in effect", "trace methods in effect"},
{"trace go method exit in effect for", "trace go method exit in effect for {0}"},
{"trace go method exits in effect", "trace go method exits in effect"},
{"trace go methods in effect", "trace go methods in effect"},
{"trace not in effect", "trace not in effect"},
{"Unable to attach to target VM.", "Unable to attach to target VM."},
{"Unable to display process output:", "Unable to display process output: {0}"},
{"Unable to launch target VM.", "Unable to launch target VM."},
{"Unable to set deferred", "Unable to set deferred {0} : {1}"},
{"Unable to set main class and arguments", "Unable to set main class and arguments"},
{"Unable to set", "Unable to set {0} : {1}"},
{"Unexpected event type", "Unexpected event type: {0}"},
{"unknown", "unknown"},
{"Unmonitoring", "Unmonitoring {0} "},
{"Unrecognized command. Try help...", "Unrecognized command: ''{0}''. Try help..."},
{"Usage: catch exception", "Usage: catch [uncaught|caught|all] <class id>|<class pattern>"},
{"Usage: ignore exception", "Usage: ignore [uncaught|caught|all] <class id>|<class pattern>"},
{"Usage: down [n frames]", "Usage: down [n frames]"},
{"Usage: kill <thread id> <throwable>", "Usage: kill <thread id> <throwable>"},
{"Usage: read <command-filename>", "Usage: read <command-filename>"},
{"Usage: unmonitor <monitor#>", "Usage: unmonitor <monitor#>"},
{"Usage: up [n frames]", "Usage: up [n frames]"},
{"Use java minus X to see", "Use 'java -X' to see the available non-standard options"},
{"Use stop at to set a breakpoint at a line number", "Use 'stop at' to set a breakpoint at a line number"},
{"VM already running. use cont to continue after events.", "VM already running. Use 'cont' to continue after events."},
{"VM Started:", "VM Started: "},
{"vmstartexception", "VM start exception: {0}"},
{"Waiting for monitor:", " Waiting for monitor: {0}"},
{"Waiting thread:", " Waiting thread: {0}"},
{"watch accesses of", "watch accesses of {0}.{1}"},
{"watch modification of", "watch modification of {0}.{1}"},
{"zz help text",
"** command list **\n" +
"connectors -- list available connectors and transports in this VM\n" +
"\n" +
"run [class [args]] -- start execution of application's main class\n" +
"\n" +
"threads [threadgroup] -- list threads\n" +
"thread <thread id> -- set default thread\n" +
"suspend [thread id(s)] -- suspend threads (default: all)\n" +
"resume [thread id(s)] -- resume threads (default: all)\n" +
"where [<thread id> | all] -- dump a thread's stack\n" +
"wherei [<thread id> | all]-- dump a thread's stack, with pc info\n" +
"up [n frames] -- move up a thread's stack\n" +
"down [n frames] -- move down a thread's stack\n" +
"kill <thread id> <expr> -- kill a thread with the given exception object\n" +
"interrupt <thread id> -- interrupt a thread\n" +
"\n" +
"print <expr> -- print value of expression\n" +
"dump <expr> -- print all object information\n" +
"eval <expr> -- evaluate expression (same as print)\n" +
"set <lvalue> = <expr> -- assign new value to field/variable/array element\n" +
"locals -- print all local variables in current stack frame\n" +
"\n" +
"classes -- list currently known classes\n" +
"class <class id> -- show details of named class\n" +
"methods <class id> -- list a class's methods\n" +
"fields <class id> -- list a class's fields\n" +
"\n" +
"threadgroups -- list threadgroups\n" +
"threadgroup <name> -- set current threadgroup\n" +
"\n" +
"stop in <class id>.<method>[(argument_type,...)]\n" +
" -- set a breakpoint in a method\n" +
"stop at <class id>:<line> -- set a breakpoint at a line\n" +
"clear <class id>.<method>[(argument_type,...)]\n" +
" -- clear a breakpoint in a method\n" +
"clear <class id>:<line> -- clear a breakpoint at a line\n" +
"clear -- list breakpoints\n" +
"catch [uncaught|caught|all] <class id>|<class pattern>\n" +
" -- break when specified exception occurs\n" +
"ignore [uncaught|caught|all] <class id>|<class pattern>\n" +
" -- cancel 'catch' for the specified exception\n" +
"watch [access|all] <class id>.<field name>\n" +
" -- watch access/modifications to a field\n" +
"unwatch [access|all] <class id>.<field name>\n" +
" -- discontinue watching access/modifications to a field\n" +
"trace [go] methods [thread]\n" +
" -- trace method entries and exits.\n" +
" -- All threads are suspended unless 'go' is specified\n" +
"trace [go] method exit | exits [thread]\n" +
" -- trace the current method's exit, or all methods' exits\n" +
" -- All threads are suspended unless 'go' is specified\n" +
"untrace [methods] -- stop tracing method entrys and/or exits\n" +
"step -- execute current line\n" +
"step up -- execute until the current method returns to its caller\n" +
"stepi -- execute current instruction\n" +
"next -- step one line (step OVER calls)\n" +
"cont -- continue execution from breakpoint\n" +
"\n" +
"list [line number|method] -- print source code\n" +
"use (or sourcepath) [source file path]\n" +
" -- display or change the source path\n" +
"exclude [<class pattern>, ... | \"none\"]\n" +
" -- do not report step or method events for specified classes\n" +
"classpath -- print classpath info from target VM\n" +
"\n" +
"monitor <command> -- execute command each time the program stops\n" +
"monitor -- list monitors\n" +
"unmonitor <monitor#> -- delete a monitor\n" +
"read <filename> -- read and execute a command file\n" +
"\n" +
"lock <expr> -- print lock info for an object\n" +
"threadlocks [thread id] -- print lock info for a thread\n" +
"\n" +
"pop -- pop the stack through and including the current frame\n" +
"reenter -- same as pop, but current frame is reentered\n" +
"redefine <class id> <class file name>\n" +
" -- redefine the code for a class\n" +
"\n" +
"disablegc <expr> -- prevent garbage collection of an object\n" +
"enablegc <expr> -- permit garbage collection of an object\n" +
"\n" +
"!! -- repeat last command\n" +
"<n> <command> -- repeat command n times\n" +
"# <command> -- discard (no-op)\n" +
"help (or ?) -- list commands\n" +
"version -- print version information\n" +
"exit (or quit) -- exit debugger\n" +
"\n" +
"<class id>: a full class name with package qualifiers\n" +
"<class pattern>: a class name with a leading or trailing wildcard ('*')\n" +
"<thread id>: thread number as reported in the 'threads' command\n" +
"<expr>: a Java(TM) Programming Language expression.\n" +
"Most common syntax is supported.\n" +
"\n" +
"Startup commands can be placed in either \"jdb.ini\" or \".jdbrc\"\n" +
"in user.home or user.dir"},
{"zz usage text",
"Usage: {0} <options> <class> <arguments>\n" +
"\n" +
"where options include:\n" +
" -help print out this message and exit\n" +
" -sourcepath <directories separated by \"{1}\">\n" +
" directories in which to look for source files\n" +
" -attach <address>\n" +
" attach to a running VM at the specified address using standard connector\n" +
" -listen <address>\n" +
" wait for a running VM to connect at the specified address using standard connector\n" +
" -listenany\n" +
" wait for a running VM to connect at any available address using standard connector\n" +
" -launch\n" +
" launch VM immediately instead of waiting for ''run'' command\n" +
" -listconnectors list the connectors available in this VM\n" +
" -connect <connector-name>:<name1>=<value1>,...\n" +
" connect to target VM using named connector with listed argument values\n" +
" -dbgtrace [flags] print info for debugging {0}\n" +
" -tclient run the application in the HotSpot(TM) Client Compiler\n" +
" -tserver run the application in the HotSpot(TM) Server Compiler\n" +
"\n" +
"options forwarded to debuggee process:\n" +
" -v -verbose[:class|gc|jni]\n" +
" turn on verbose mode\n" +
" -D<name>=<value> set a system property\n" +
" -classpath <directories separated by \"{1}\">\n" +
" list directories in which to look for classes\n" +
" -X<option> non-standard target VM option\n" +
"\n" +
"<class> is the name of the class to begin debugging\n" +
"<arguments> are the arguments passed to the main() method of <class>\n" +
"\n" +
"For command help type ''help'' at {0} prompt"},
// END OF MATERIAL TO LOCALIZE
};
return temp;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.ThreadGroupReference;
import java.util.List;
import java.util.Stack;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Descend the tree of thread groups.
* @author Robert G. Field
*/
class ThreadGroupIterator implements Iterator<ThreadGroupReference> {
private final Stack<Iterator<ThreadGroupReference>> stack = new Stack<Iterator<ThreadGroupReference>>();
ThreadGroupIterator(List<ThreadGroupReference> tgl) {
push(tgl);
}
ThreadGroupIterator(ThreadGroupReference tg) {
List<ThreadGroupReference> tgl = new ArrayList<ThreadGroupReference>();
tgl.add(tg);
push(tgl);
}
ThreadGroupIterator() {
this(Env.vm().topLevelThreadGroups());
}
private Iterator<ThreadGroupReference> top() {
return stack.peek();
}
/**
* The invariant in this class is that the top iterator
* on the stack has more elements. If the stack is
* empty, there is no top. This method assures
* this invariant.
*/
private void push(List<ThreadGroupReference> tgl) {
stack.push(tgl.iterator());
while (!stack.isEmpty() && !top().hasNext()) {
stack.pop();
}
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public ThreadGroupReference next() {
return nextThreadGroup();
}
public ThreadGroupReference nextThreadGroup() {
ThreadGroupReference tg = top().next();
push(tg.threadGroups());
return tg;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
static ThreadGroupReference find(String name) {
ThreadGroupIterator tgi = new ThreadGroupIterator();
while (tgi.hasNext()) {
ThreadGroupReference tg = tgi.nextThreadGroup();
if (tg.name().equals(name)) {
return tg;
}
}
return null;
}
}

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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.ThreadGroupReference;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.StackFrame;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
class ThreadInfo {
// This is a list of all known ThreadInfo objects. It survives
// ThreadInfo.invalidateAll, unlike the other static fields below.
private static List<ThreadInfo> threads = Collections.synchronizedList(new ArrayList<ThreadInfo>());
private static boolean gotInitialThreads = false;
private static ThreadInfo current = null;
private static ThreadGroupReference group = null;
private final ThreadReference thread;
private int currentFrameIndex = 0;
private ThreadInfo(ThreadReference thread) {
this.thread = thread;
if (thread == null) {
MessageOutput.fatalError("Internal error: null ThreadInfo created");
}
}
private static void initThreads() {
if (!gotInitialThreads) {
for (ThreadReference thread : Env.vm().allThreads()) {
threads.add(new ThreadInfo(thread));
}
gotInitialThreads = true;
}
}
static void addThread(ThreadReference thread) {
synchronized (threads) {
initThreads();
ThreadInfo ti = new ThreadInfo(thread);
// Guard against duplicates. Duplicates can happen during
// initialization when a particular thread might be added both
// by a thread start event and by the initial call to threads()
if (getThreadInfo(thread) == null) {
threads.add(ti);
}
}
}
static void removeThread(ThreadReference thread) {
if (thread.equals(ThreadInfo.current)) {
// Current thread has died.
// Be careful getting the thread name. If its death happens
// as part of VM termination, it may be too late to get the
// information, and an exception will be thrown.
String currentThreadName;
try {
currentThreadName = "\"" + thread.name() + "\"";
} catch (Exception e) {
currentThreadName = "";
}
setCurrentThread(null);
MessageOutput.println();
MessageOutput.println("Current thread died. Execution continuing...",
currentThreadName);
}
threads.remove(getThreadInfo(thread));
}
static List<ThreadInfo> threads() {
synchronized(threads) {
initThreads();
// Make a copy to allow iteration without synchronization
return new ArrayList<ThreadInfo>(threads);
}
}
static void invalidateAll() {
current = null;
group = null;
synchronized (threads) {
for (ThreadInfo ti : threads()) {
ti.invalidate();
}
}
}
static void setThreadGroup(ThreadGroupReference tg) {
group = tg;
}
static void setCurrentThread(ThreadReference tr) {
if (tr == null) {
setCurrentThreadInfo(null);
} else {
ThreadInfo tinfo = getThreadInfo(tr);
setCurrentThreadInfo(tinfo);
}
}
static void setCurrentThreadInfo(ThreadInfo tinfo) {
current = tinfo;
if (current != null) {
current.invalidate();
}
}
/**
* Get the current ThreadInfo object.
*
* @return the ThreadInfo for the current thread.
*/
static ThreadInfo getCurrentThreadInfo() {
return current;
}
/**
* Get the thread from this ThreadInfo object.
*
* @return the Thread wrapped by this ThreadInfo.
*/
ThreadReference getThread() {
return thread;
}
static ThreadGroupReference group() {
if (group == null) {
// Current thread group defaults to the first top level
// thread group.
setThreadGroup(Env.vm().topLevelThreadGroups().get(0));
}
return group;
}
static ThreadInfo getThreadInfo(long id) {
ThreadInfo retInfo = null;
synchronized (threads) {
for (ThreadInfo ti : threads()) {
if (ti.thread.uniqueID() == id) {
retInfo = ti;
break;
}
}
}
return retInfo;
}
static ThreadInfo getThreadInfo(ThreadReference tr) {
return getThreadInfo(tr.uniqueID());
}
static ThreadInfo getThreadInfo(String idToken) {
ThreadInfo tinfo = null;
if (idToken.startsWith("t@")) {
idToken = idToken.substring(2);
}
try {
long threadId = Long.decode(idToken).longValue();
tinfo = getThreadInfo(threadId);
} catch (NumberFormatException e) {
tinfo = null;
}
return tinfo;
}
/**
* Get the thread stack frames.
*
* @return a <code>List</code> of the stack frames.
*/
List<StackFrame> getStack() throws IncompatibleThreadStateException {
return thread.frames();
}
/**
* Get the current stackframe.
*
* @return the current stackframe.
*/
StackFrame getCurrentFrame() throws IncompatibleThreadStateException {
if (thread.frameCount() == 0) {
return null;
}
return thread.frame(currentFrameIndex);
}
/**
* Invalidate the current stackframe index.
*/
void invalidate() {
currentFrameIndex = 0;
}
/* Throw IncompatibleThreadStateException if not suspended */
private void assureSuspended() throws IncompatibleThreadStateException {
if (!thread.isSuspended()) {
throw new IncompatibleThreadStateException();
}
}
/**
* Get the current stackframe index.
*
* @return the number of the current stackframe. Frame zero is the
* closest to the current program counter
*/
int getCurrentFrameIndex() {
return currentFrameIndex;
}
/**
* Set the current stackframe to a specific frame.
*
* @param nFrame the number of the desired stackframe. Frame zero is the
* closest to the current program counter
* @exception IllegalAccessError when the thread isn't
* suspended or waiting at a breakpoint
* @exception ArrayIndexOutOfBoundsException when the
* requested frame is beyond the stack boundary
*/
void setCurrentFrameIndex(int nFrame) throws IncompatibleThreadStateException {
assureSuspended();
if ((nFrame < 0) || (nFrame >= thread.frameCount())) {
throw new ArrayIndexOutOfBoundsException();
}
currentFrameIndex = nFrame;
}
/**
* Change the current stackframe to be one or more frames higher
* (as in, away from the current program counter).
*
* @param nFrames the number of stackframes
* @exception IllegalAccessError when the thread isn't
* suspended or waiting at a breakpoint
* @exception ArrayIndexOutOfBoundsException when the
* requested frame is beyond the stack boundary
*/
void up(int nFrames) throws IncompatibleThreadStateException {
setCurrentFrameIndex(currentFrameIndex + nFrames);
}
/**
* Change the current stackframe to be one or more frames lower
* (as in, toward the current program counter). *
* @param nFrames the number of stackframes
* @exception IllegalAccessError when the thread isn't
* suspended or waiting at a breakpoint
* @exception ArrayIndexOutOfBoundsException when the
* requested frame is beyond the stack boundary
*/
void down(int nFrames) throws IncompatibleThreadStateException {
setCurrentFrameIndex(currentFrameIndex - nFrames);
}
}

View File

@@ -0,0 +1,82 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.ThreadGroupReference;
import com.sun.jdi.ThreadReference;
import java.util.List;
import java.util.Iterator;
class ThreadIterator implements Iterator<ThreadReference> {
Iterator<ThreadReference> it = null;
ThreadGroupIterator tgi;
ThreadIterator(ThreadGroupReference tg) {
tgi = new ThreadGroupIterator(tg);
}
ThreadIterator(List<ThreadGroupReference> tgl) {
tgi = new ThreadGroupIterator(tgl);
}
ThreadIterator() {
tgi = new ThreadGroupIterator();
}
@Override
public boolean hasNext() {
while (it == null || !it.hasNext()) {
if (!tgi.hasNext()) {
return false; // no more
}
it = tgi.nextThreadGroup().threads().iterator();
}
return true;
}
@Override
public ThreadReference next() {
return it.next();
}
public ThreadReference nextThread() {
return next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,548 @@
/*
* Copyright (c) 1998, 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
import com.sun.jdi.*;
import com.sun.jdi.connect.*;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.ThreadStartRequest;
import com.sun.jdi.request.ThreadDeathRequest;
import java.util.*;
import java.util.regex.*;
import java.io.*;
class VMConnection {
private VirtualMachine vm;
private Process process = null;
private int outputCompleteCount = 0;
private final Connector connector;
private final Map<String, com.sun.jdi.connect.Connector.Argument> connectorArgs;
private final int traceFlags;
synchronized void notifyOutputComplete() {
outputCompleteCount++;
notifyAll();
}
synchronized void waitOutputComplete() {
// Wait for stderr and stdout
if (process != null) {
while (outputCompleteCount < 2) {
try {wait();} catch (InterruptedException e) {}
}
}
}
private Connector findConnector(String name) {
for (Connector connector :
Bootstrap.virtualMachineManager().allConnectors()) {
if (connector.name().equals(name)) {
return connector;
}
}
return null;
}
private Map <String, com.sun.jdi.connect.Connector.Argument> parseConnectorArgs(Connector connector, String argString) {
Map<String, com.sun.jdi.connect.Connector.Argument> arguments = connector.defaultArguments();
/*
* We are parsing strings of the form:
* name1=value1,[name2=value2,...]
* However, the value1...valuen substrings may contain
* embedded comma(s), so make provision for quoting inside
* the value substrings. (Bug ID 4285874)
*/
String regexPattern =
"(quote=[^,]+,)|" + // special case for quote=.,
"(\\w+=)" + // name=
"(((\"[^\"]*\")|" + // ( "l , ue"
"('[^']*')|" + // 'l , ue'
"([^,'\"]+))+,)"; // v a l u e )+ ,
Pattern p = Pattern.compile(regexPattern);
Matcher m = p.matcher(argString);
while (m.find()) {
int startPosition = m.start();
int endPosition = m.end();
if (startPosition > 0) {
/*
* It is an error if parsing skips over any part of argString.
*/
throw new IllegalArgumentException
(MessageOutput.format("Illegal connector argument",
argString));
}
String token = argString.substring(startPosition, endPosition);
int index = token.indexOf('=');
String name = token.substring(0, index);
String value = token.substring(index + 1,
token.length() - 1); // Remove comma delimiter
/*
* for values enclosed in quotes (single and/or double quotes)
* strip off enclosing quote chars
* needed for quote enclosed delimited substrings
*/
if (name.equals("options")) {
StringBuilder sb = new StringBuilder();
for (String s : splitStringAtNonEnclosedWhiteSpace(value)) {
while (isEnclosed(s, "\"") || isEnclosed(s, "'")) {
s = s.substring(1, s.length() - 1);
}
sb.append(s);
sb.append(" ");
}
value = sb.toString();
}
Connector.Argument argument = arguments.get(name);
if (argument == null) {
throw new IllegalArgumentException
(MessageOutput.format("Argument is not defined for connector:",
new Object [] {name, connector.name()}));
}
argument.setValue(value);
argString = argString.substring(endPosition); // Remove what was just parsed...
m = p.matcher(argString); // and parse again on what is left.
}
if ((! argString.equals(",")) && (argString.length() > 0)) {
/*
* It is an error if any part of argString is left over,
* unless it was empty to begin with.
*/
throw new IllegalArgumentException
(MessageOutput.format("Illegal connector argument", argString));
}
return arguments;
}
private static boolean isEnclosed(String value, String enclosingChar) {
if (value.indexOf(enclosingChar) == 0) {
int lastIndex = value.lastIndexOf(enclosingChar);
if (lastIndex > 0 && lastIndex == value.length() - 1) {
return true;
}
}
return false;
}
private static List<String> splitStringAtNonEnclosedWhiteSpace(String value) throws IllegalArgumentException {
List<String> al = new ArrayList<String>();
char[] arr;
int startPosition = 0;
int endPosition = 0;
final char SPACE = ' ';
final char DOUBLEQ = '"';
final char SINGLEQ = '\'';
/*
* An "open" or "active" enclosing state is where
* the first valid start quote qualifier is found,
* and there is a search in progress for the
* relevant end matching quote
*
* enclosingTargetChar set to SPACE
* is used to signal a non open enclosing state
*/
char enclosingTargetChar = SPACE;
if (value == null) {
throw new IllegalArgumentException
(MessageOutput.format("value string is null"));
}
// split parameter string into individual chars
arr = value.toCharArray();
for (int i = 0; i < arr.length; i++) {
switch (arr[i]) {
case SPACE: {
// do nothing for spaces
// unless last in array
if (isLastChar(arr, i)) {
endPosition = i;
// break for substring creation
break;
}
continue;
}
case DOUBLEQ:
case SINGLEQ: {
if (enclosingTargetChar == arr[i]) {
// potential match to close open enclosing
if (isNextCharWhitespace(arr, i)) {
// if peek next is whitespace
// then enclosing is a valid substring
endPosition = i;
// reset enclosing target char
enclosingTargetChar = SPACE;
// break for substring creation
break;
}
}
if (enclosingTargetChar == SPACE) {
// no open enclosing state
// handle as normal char
if (isPreviousCharWhitespace(arr, i)) {
startPosition = i;
// peek forward for end candidates
if (value.indexOf(arr[i], i + 1) >= 0) {
// set open enclosing state by
// setting up the target char
enclosingTargetChar = arr[i];
} else {
// no more target chars left to match
// end enclosing, handle as normal char
if (isNextCharWhitespace(arr, i)) {
endPosition = i;
// break for substring creation
break;
}
}
}
}
continue;
}
default: {
// normal non-space, non-" and non-' chars
if (enclosingTargetChar == SPACE) {
// no open enclosing state
if (isPreviousCharWhitespace(arr, i)) {
// start of space delim substring
startPosition = i;
}
if (isNextCharWhitespace(arr, i)) {
// end of space delim substring
endPosition = i;
// break for substring creation
break;
}
}
continue;
}
}
// break's end up here
if (startPosition > endPosition) {
throw new IllegalArgumentException
(MessageOutput.format("Illegal option values"));
}
// extract substring and add to List<String>
al.add(value.substring(startPosition, ++endPosition));
// set new start position
i = startPosition = endPosition;
} // for loop
return al;
}
static private boolean isPreviousCharWhitespace(char[] arr, int curr_pos) {
return isCharWhitespace(arr, curr_pos - 1);
}
static private boolean isNextCharWhitespace(char[] arr, int curr_pos) {
return isCharWhitespace(arr, curr_pos + 1);
}
static private boolean isCharWhitespace(char[] arr, int pos) {
if (pos < 0 || pos >= arr.length) {
// outside arraybounds is considered an implicit space
return true;
}
if (arr[pos] == ' ') {
return true;
}
return false;
}
static private boolean isLastChar(char[] arr, int pos) {
return (pos + 1 == arr.length);
}
VMConnection(String connectSpec, int traceFlags) {
String nameString;
String argString;
int index = connectSpec.indexOf(':');
if (index == -1) {
nameString = connectSpec;
argString = "";
} else {
nameString = connectSpec.substring(0, index);
argString = connectSpec.substring(index + 1);
}
connector = findConnector(nameString);
if (connector == null) {
throw new IllegalArgumentException
(MessageOutput.format("No connector named:", nameString));
}
connectorArgs = parseConnectorArgs(connector, argString);
this.traceFlags = traceFlags;
}
synchronized VirtualMachine open() {
if (connector instanceof LaunchingConnector) {
vm = launchTarget();
} else if (connector instanceof AttachingConnector) {
vm = attachTarget();
} else if (connector instanceof ListeningConnector) {
vm = listenTarget();
} else {
throw new InternalError
(MessageOutput.format("Invalid connect type"));
}
vm.setDebugTraceMode(traceFlags);
if (vm.canBeModified()){
setEventRequests(vm);
resolveEventRequests();
}
/*
* Now that the vm connection is open, fetch the debugee
* classpath and set up a default sourcepath.
* (Unless user supplied a sourcepath on the command line)
* (Bug ID 4186582)
*/
if (Env.getSourcePath().length() == 0) {
if (vm instanceof PathSearchingVirtualMachine) {
PathSearchingVirtualMachine psvm =
(PathSearchingVirtualMachine) vm;
Env.setSourcePath(psvm.classPath());
} else {
Env.setSourcePath(".");
}
}
return vm;
}
boolean setConnectorArg(String name, String value) {
/*
* Too late if the connection already made
*/
if (vm != null) {
return false;
}
Connector.Argument argument = connectorArgs.get(name);
if (argument == null) {
return false;
}
argument.setValue(value);
return true;
}
String connectorArg(String name) {
Connector.Argument argument = connectorArgs.get(name);
if (argument == null) {
return "";
}
return argument.value();
}
public synchronized VirtualMachine vm() {
if (vm == null) {
throw new VMNotConnectedException();
} else {
return vm;
}
}
boolean isOpen() {
return (vm != null);
}
boolean isLaunch() {
return (connector instanceof LaunchingConnector);
}
public void disposeVM() {
try {
if (vm != null) {
vm.dispose();
vm = null;
}
} finally {
if (process != null) {
process.destroy();
process = null;
}
waitOutputComplete();
}
}
private void setEventRequests(VirtualMachine vm) {
EventRequestManager erm = vm.eventRequestManager();
// Normally, we want all uncaught exceptions. We request them
// via the same mechanism as Commands.commandCatchException()
// so the user can ignore them later if they are not
// interested.
// FIXME: this works but generates spurious messages on stdout
// during startup:
// Set uncaught java.lang.Throwable
// Set deferred uncaught java.lang.Throwable
Commands evaluator = new Commands();
evaluator.commandCatchException
(new StringTokenizer("uncaught java.lang.Throwable"));
ThreadStartRequest tsr = erm.createThreadStartRequest();
tsr.enable();
ThreadDeathRequest tdr = erm.createThreadDeathRequest();
tdr.enable();
}
private void resolveEventRequests() {
Env.specList.resolveAll();
}
private void dumpStream(InputStream stream) throws IOException {
BufferedReader in =
new BufferedReader(new InputStreamReader(stream));
int i;
try {
while ((i = in.read()) != -1) {
MessageOutput.printDirect((char)i);// Special case: use
// printDirect()
}
} catch (IOException ex) {
String s = ex.getMessage();
if (!s.startsWith("Bad file number")) {
throw ex;
}
// else we got a Bad file number IOException which just means
// that the debuggee has gone away. We'll just treat it the
// same as if we got an EOF.
}
}
/**
* Create a Thread that will retrieve and display any output.
* Needs to be high priority, else debugger may exit before
* it can be displayed.
*/
private void displayRemoteOutput(final InputStream stream) {
Thread thr = new Thread("output reader") {
@Override
public void run() {
try {
dumpStream(stream);
} catch (IOException ex) {
MessageOutput.fatalError("Failed reading output");
} finally {
notifyOutputComplete();
}
}
};
thr.setPriority(Thread.MAX_PRIORITY-1);
thr.start();
}
private void dumpFailedLaunchInfo(Process process) {
try {
dumpStream(process.getErrorStream());
dumpStream(process.getInputStream());
} catch (IOException e) {
MessageOutput.println("Unable to display process output:",
e.getMessage());
}
}
/* launch child target vm */
private VirtualMachine launchTarget() {
LaunchingConnector launcher = (LaunchingConnector)connector;
try {
VirtualMachine vm = launcher.launch(connectorArgs);
process = vm.process();
displayRemoteOutput(process.getErrorStream());
displayRemoteOutput(process.getInputStream());
return vm;
} catch (IOException ioe) {
ioe.printStackTrace();
MessageOutput.fatalError("Unable to launch target VM.");
} catch (IllegalConnectorArgumentsException icae) {
icae.printStackTrace();
MessageOutput.fatalError("Internal debugger error.");
} catch (VMStartException vmse) {
MessageOutput.println("vmstartexception", vmse.getMessage());
MessageOutput.println();
dumpFailedLaunchInfo(vmse.process());
MessageOutput.fatalError("Target VM failed to initialize.");
}
return null; // Shuts up the compiler
}
/* attach to running target vm */
private VirtualMachine attachTarget() {
AttachingConnector attacher = (AttachingConnector)connector;
try {
return attacher.attach(connectorArgs);
} catch (IOException ioe) {
ioe.printStackTrace();
MessageOutput.fatalError("Unable to attach to target VM.");
} catch (IllegalConnectorArgumentsException icae) {
icae.printStackTrace();
MessageOutput.fatalError("Internal debugger error.");
}
return null; // Shuts up the compiler
}
/* listen for connection from target vm */
private VirtualMachine listenTarget() {
ListeningConnector listener = (ListeningConnector)connector;
try {
String retAddress = listener.startListening(connectorArgs);
MessageOutput.println("Listening at address:", retAddress);
vm = listener.accept(connectorArgs);
listener.stopListening(connectorArgs);
return vm;
} catch (IOException ioe) {
ioe.printStackTrace();
MessageOutput.fatalError("Unable to attach to target VM.");
} catch (IllegalConnectorArgumentsException icae) {
icae.printStackTrace();
MessageOutput.fatalError("Internal debugger error.");
}
return null; // Shuts up the compiler
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
public class VMNotConnectedException extends RuntimeException {
private static final long serialVersionUID = -7433430494903950165L;
public VMNotConnectedException() {
super();
}
public VMNotConnectedException(String s) {
super(s);
}
}

View File

@@ -0,0 +1,77 @@
/*
* 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.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.tools.example.debug.tty;
abstract class WatchpointSpec extends EventRequestSpec {
final String fieldId;
WatchpointSpec(ReferenceTypeSpec refSpec, String fieldId)
throws MalformedMemberNameException {
super(refSpec);
this.fieldId = fieldId;
if (!isJavaIdentifier(fieldId)) {
throw new MalformedMemberNameException(fieldId);
}
}
@Override
public int hashCode() {
return refSpec.hashCode() + fieldId.hashCode() +
getClass().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof WatchpointSpec) {
WatchpointSpec watchpoint = (WatchpointSpec)obj;
return fieldId.equals(watchpoint.fieldId) &&
refSpec.equals(watchpoint.refSpec) &&
getClass().equals(watchpoint.getClass());
} else {
return false;
}
}
@Override
String errorMessageFor(Exception e) {
if (e instanceof NoSuchFieldException) {
return (MessageOutput.format("No field in",
new Object [] {fieldId, refSpec.toString()}));
} else {
return super.errorMessageFor(e);
}
}
}