Name: mc57594 Date: 02/21/97
The following class illustrates the following bugs and misfeatures:
1. (MISFEATURE) Passing null as the first argument to
RemoteDebugger(String, DebuggerCallback, boolean) causes
inferior to crash.
2. (BUG) Local variables which are not method parameters are not
seen by getLocalVariable() or getLocalVariables().
3. (BUG) Attempting to retrieve a field value from RemoteObject
using getFieldValue() (either variant) causes the inferior
JVM to crash.
4. (MISFEATURE) There is no threadCreatedEvent() so the only
way to pick up new threads is to poll.
To reproduce #2 and #3 compile this test case:
javac -g RemoteObjectBug.java
and run it:
java frostbytes.bugs.RemoteObjectBug
-- cut here (RemoteObjectBug.java) --
// RemoteObjectBug.java:
//
// jim frost 02.18.97
package frostbytes.bugs;
import sun.tools.debug.*;
public class RemoteObjectBug implements DebuggerCallback
{
/**
* Constructor used when invoked as the superior.
*/
private RemoteObjectBug()
{
// kick off the inferior
//
RemoteDebugger debugger;
try {
// MISFEATURE: if you pass null as the first argument, the
// inferior crashes.
//
debugger = new RemoteDebugger("", this, true);
}
catch (Exception e) {
System.out.println("Could not create RemoteDebugger object.");
return;
}
String[] args = {
this.getClass().getName(),
"test"
};
RemoteThreadGroup rootThreadGroup;
try {
rootThreadGroup = debugger.run(args.length, args);
}
catch (Exception e) {
System.out.println("Could not run inferior.");
return;
}
// get the test thread
//
System.out.println("Retrieving main thread.");
RemoteThread rthread = getMainThread(rootThreadGroup);
if (rthread == null)
return;
// wait a second to make sure the thread makes it far enough along
//
sleep(2000);
// stop the test thread
//
System.out.println("Suspending main thread");
try {
rthread.suspend();
}
catch (Exception e) {
System.out.println("Unable to suspend inferior.");
}
// find the 'main' frame
//
System.out.println("Looking for inferior() frame");
RemoteStackFrame rframe = getInferiorFrame(rthread);
// BUG: can't find local variable which is not an argument.
//
RemoteStackVariable rvar = null;
System.out.println("Looking for 'i'");
try {
rvar = rframe.getLocalVariable("i");
if (rvar == null)
System.out.println("No i variable found in frame. The variables I know about are:");
printFrameLocals(rframe);
}
catch (Exception e) {
System.out.println("Unable to retrieve i variable: " + e);
}
// look up the "testObject" variable in the frame
//
System.out.println("Retrieving 'testObject'");
try {
rvar = rframe.getLocalVariable("testObject");
}
catch (Exception e) {
System.out.println("Unable to retrieve testObject variable: " + e);
return;
}
if (rvar == null) {
System.out.println("No testObject variable, sorry");
return;
}
System.out.println("Have testObject variable");
// retrieve the value of the variable
//
System.out.println("Retrieving testObject's value");
RemoteObject robject;
try {
robject = (RemoteObject)rvar.getValue();
}
catch (Exception e) {
System.out.println("Unable to retrieve testObject's value: " + e);
return;
}
// BUG: attempting to retrieve the value of an object member
// causes the inferior's JVM to crash.
//
System.out.println("Retrieving TestObject.i");
RemoteValue memberValue;
try {
memberValue = robject.getFieldValue("i");
}
catch (Exception e) {
System.out.println("Unable to retrive TestObject.i");
return;
}
System.out.println("TestObject.i = " + memberValue);
debugger.close();
}
/**
* Retrieves the "this" object for the RemoteObjectBug initializer frame.
*/
private RemoteStackFrame getInferiorFrame(RemoteThread rthread)
{
try {
for (;;) {
RemoteStackFrame rframe = rthread.getCurrentFrame();
if (rframe == null)
break;
String className = rframe.getRemoteClass().getName();
String methodName = rframe.getMethodName();
if (className.equals(getClass().getName()) &&
methodName.equals("inferior")) {
System.out.println("Found " + className + "." + methodName + "()");
return rframe;
}
else {
System.out.println("Skipping frame for " + className + "." + methodName + "()");
rthread.up(1);
}
}
}
catch (Exception e) {
System.out.println("Exception while performing traceback: " + e);
}
System.out.println("Didn't find stack frame for " + getClass().getName());
System.exit(1);
return null; // NOTREACHED
}
private String getThreadName(RemoteThread rthread)
{
try {
return rthread.getName();
}
catch (Exception e) {
return "<unknown>";
}
}
public static void inferior(TestObject testObject)
{
System.out.println("Inferior is up and running.");
for (;;)
sleep(10000);
}
/**
* Application startup harness.
*/
public static void main(String[] args)
{
TestObject testObject = new TestObject();
if (args.length > 0)
inferior(new TestObject());
else
new RemoteObjectBug();
}
private void printFrameLocals(RemoteStackFrame rframe)
{
RemoteStackVariable[] rvars;
try {
rvars = rframe.getLocalVariables();
}
catch (Exception e) {
System.out.println("Unable to retrieve frame locals: " + e);
rvars = null;
}
if ((rvars == null) || (rvars.length == 0))
System.out.println("<No local variables>");
else {
for (int i = 0; i < rvars.length; i++) {
System.out.println(rvars[i].getName());
}
}
}
private static void sleep(int ms)
{
try {
Thread.currentThread().sleep(ms);
}
catch (InterruptedException e) {}
}
/**
* Finds the main thread in the inferior.
*/
private RemoteThread getMainThread(RemoteThreadGroup rootThreadGroup)
{
RemoteThread[] threads;
try {
threads = rootThreadGroup.listThreads(true);
}
catch (Exception e) {
threads = null;
}
if (threads == null) {
System.out.println("Unable to list threads!");
return null;
}
// find the thread in the list
//
for (int i = 0; i < threads.length; i++) {
String threadName = getThreadName(threads[i]);
if (threadName.equals("main"))
return threads[i];
}
System.out.println("Didn't find main thread!");
return null;
}
///////////////////////////////////////////////
// DebuggerCallback interface implementation //
///////////////////////////////////////////////
public void printToConsole(String text)
{
System.out.print(text);
}
public void breakpointEvent(RemoteThread rthread)
{
}
public void exceptionEvent(RemoteThread rthread, String errorText)
{
System.out.println("Inferior saw exception: " + errorText);
}
// MISFEATURE: no event sent on thread creation.
//
public void threadDeathEvent(RemoteThread rthread)
{
String threadName;
try {
threadName = rthread.getName();
}
catch (Exception e) {
threadName = "<unknown>";
}
System.out.println("Inferior thread died: " + threadName);
}
public void quitEvent()
{
System.out.println("Inferior died, shutting down.");
System.exit(0);
}
}
class TestObject
{
private int i;
}
company - Frostbytes Software , email - ###@###.###
======================================================================
- duplicates
-
JDK-4026633 Trying to print "method" fails in jdb
- Closed
-
JDK-4031082 sun.tools.debug.RemoteClass.getFieldValue crashes
- Closed