Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Language IDEs » Java Development Tools (JDT) » JDT Debug Tools Help
JDT Debug Tools Help [message #894873] Tue, 10 July 2012 20:56 Go to next message
Matt R is currently offline Matt RFriend
Messages: 6
Registered: July 2012
Junior Member
Hi,

I'm new to eclipse plugin development/debugger development, and I'm currently working on a project with this scenario:

What I'm trying to do is I have this framework/API built on Java, and I would like to write an eclipse plugin debugger that is customized to my framework. Here is a simple example:

I have two classes, one called scope and one called variable. The scope holds a map of variables. The code is all in java, but I'm using this scope-variable relationship almost like a new language, and would like a variable debug tab that gives me a list of currently active scopes with the variables that are currently stored inside. Here is some code:
import java.util.Hashtable;

public class Scope {
    private Hashtable<String, Variable> variableList = new Hashtable<String, Variable>();

   // constructor 
    public Scope(){

    }

    public void put(String key, Variable v){
        variableList.put(key, v);
    }

    public Variable get(String key){
        return variableList.get(key);
    }


}

public class Variable {

    private String value;
    private String name;

    public Variable(String aName, String aValue){
        name = aName;
        value = aValue;
    }

    public String getValue(){
        return value;
    }

    public String getName(){
        return name;
    }

    public void setValue(String aValue){
        value = aValue;
    }
}


This example is simplified; the actual scope-variable relation I am working with is more complex, such that you have a scope which is a container of something, which is a container of something...some container holds variables; basically the hierarchy is complicated and is not easily navigable with the variables view.

Goal: I want to be able to create a view that is similar to a variables view, but only shows scope-variable relationships ignoring all the stuff in between that would make up the complex java hierarchy behind it.

Current Solution: In order to perform what I am currently doing, I'm using the static methods of the org.eclipse.debug.ui.DebugUITools; class: the getDebugContext(). Basically this listens to debug context changes and gives me IStackFrame/IVariable/IValue interfaces that give me enough information to build the complicated hierarchy, which I later parse into the simplified view of scope-variable. Here is some code:
public class DebugContextListener implements IDebugContextListener 
{

    IStackFrameConsumer consumer;
    /**
     * Creates a new DebugContextListener.
     *
     * @param consumer
     *            an IStackFrameConsumer to which the extracted stack frame
     *            objects will be given.
     */
    public DebugContextListener(IStackFrameConsumer consumer) 
    {
        this.consumer = consumer;
    }
    
    /**
     * Notification that the debug context has changed (a new debug event has happened)
     */
    public void debugContextChanged(DebugContextEvent event) 
    {
        
        if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) 
        {
            contextActivated(event.getContext());
        }
        
    }
    
    
    // Grab the data if it is a new 
    private void contextActivated(ISelection context) 
    {
        if (context instanceof StructuredSelection) 
        {
            Object data = ((StructuredSelection) context).getFirstElement();
            if (data instanceof IJavaStackFrame) 
            {
                consumer.setStackFrame((IStackFrame) data);
            } else 
            {
                consumer.setStackFrame(null);
            }
        }
    }
    
}


    public void createPartControl(Composite parent)
    {

        // Create a new debug listener object to detect
        // debug actions
        debugListener = new DebugContextListener(this);
        DebugUITools.getDebugContextManager().addDebugContextListener(debugListener);

        // Check if there is an already started debug context
        IAdaptable dc = DebugUITools.getDebugContext();
        if (dc != null)
        {
                
                Object o = dc.getAdapter(IStackFrame.class);
                if (o instanceof IStackFrame)
                        setStackFrame((IStackFrame) o);
        }      
        
        viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);

...//more view building stuff




Ok so there are a few more classes, but this is the basic gist and most of the important code, and it works as it is intended.

Problem: The issue with this method is the only information I get from the listener are these IVariable/IValue objects, merely language independent representations of data on the stackframes, meaning my plugin cannot actually get the java objects. This means I have to write a billion loops, looping through my giant hierarchy to grab the variable that is deep within a scope objects. If I had the real java object, i could just call a get method that grabs me the variables.

Question: So as I understand it, the JDT provides another layer of java language specific tools that could possibly help me do what I want (that is, grab real java objects from the stackframe and be able to evaluate them, similar to the expressions view). This is what I am referring to: http://git.eclipse.org/c/jdt/eclipse.jdt.debug.git/tree/org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core

I am really eager for some advice on whether I am on the right track or not, and perhaps what I should be specifically looking into, as I am not very experienced with the JDT, and I can't find any good examples of anyone attempting anything similar to my project.

Thank you for reading all this, and thanks for any help.
Re: JDT Debug Tools Help [message #894890 is a reply to message #894873] Tue, 10 July 2012 22:41 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
some quick remarks:

IJavaVariable is a subtype of IVariable, so if you have an IVariable it might actually be an IJavaVariable, have you checked this?

Even with these interfaces you don't have the real Java objects, just handles. But, yes, with these handles you can, e.g., send messages to the Java object (sent via the debug protocol).


On a different note: have you seen the extension point org.eclipse.debug.core.logicalStructureTypes? Could this be used for an even simpler solution perhaps?

best,
Stephan

Re: JDT Debug Tools Help [message #894891 is a reply to message #894890] Tue, 10 July 2012 23:33 Go to previous messageGo to next message
Matt R is currently offline Matt RFriend
Messages: 6
Registered: July 2012
Junior Member
Thank you so much for your reply. If I have these handles, can you tell me how exactly this process of sending messages to the Java object works (maybe some sample code if there is some available)? This I feel is the key that can solve my problem.

In the meantime I will do some checking on the variable types, as well as look into that extension point you suggested.
Re: JDT Debug Tools Help [message #894892 is a reply to message #894891] Tue, 10 July 2012 23:47 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
The basic idea is:
IValue value= ...
if (value instanceof IJavaObject) {
    IJavaObject object= (IJavaObject) value;
    IJavaValue result = object.sendMessage(selector, methodSignature, args, thread, false);
}


You still need to find the arguments for the message send, though...

HTH
Stephan
Re: JDT Debug Tools Help [message #894897 is a reply to message #894892] Wed, 11 July 2012 00:57 Go to previous messageGo to next message
Matt R is currently offline Matt RFriend
Messages: 6
Registered: July 2012
Junior Member
I followed your suggestion and indeed the variables I have implement IJavaVariable. I'm now working on getting the sendMessage to work.

I can fill in most of the arguments I think:

selector - this is like my "get" method name
methodSignature - I can generate this with javap -s
args - whatever my get method args are

My problem is the thread. I don't quite understand what thread I'm looking to fill there, what it does, or how I am supposed to find it...

Thanks for your help once again. I feel like I am close to resolving this issue.
Re: JDT Debug Tools Help [message #895163 is a reply to message #894897] Wed, 11 July 2012 20:59 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
Matt R wrote on Wed, 11 July 2012 02:57

My problem is the thread. I don't quite understand what thread I'm looking to fill there, what it does, or how I am supposed to find it...


Well, aren't you working on a view that should visualize the object state of a suspended Java thread?

I see you already work with IJavaStackFrame - that's probably the instance which you should ask getThread().

Technically, the message send will be performed in this thread of the debug target (and with no suspended thread you cannot perform any evaluation).

best,
Stephan


Re: JDT Debug Tools Help [message #895190 is a reply to message #895163] Wed, 11 July 2012 23:34 Go to previous messageGo to next message
Matt R is currently offline Matt RFriend
Messages: 6
Registered: July 2012
Junior Member
Yes you are right. I have now been able to successfully send messages to the JVM and get back results.

There is however one last problem I'm facing, which is, I do not know how to construct custom arguments for the sendMessage method.

The 'args' parameter requires an array of IJavaValue, but I do not know how to create an IJavaValue. Right now I can grab other IValues on my stackframe and insert as args successfully, but sometimes I just want to insert a number. For example I just want to call get(someNumber) on an arraylist, but I don't know how to turn an int that I want to use as the index into an IJavaValue.

Thanks for all your help. My problem is basically resolved minus this one last issue.
Re: JDT Debug Tools Help [message #895194 is a reply to message #895190] Wed, 11 July 2012 23:50 Go to previous messageGo to next message
Stephan Herrmann is currently offline Stephan HerrmannFriend
Messages: 1853
Registered: July 2009
Senior Member
ask any DebugElement (e.g., the IJavaThread) for its DebugTarget, supposed to be an IJavaDebugTarget, which in turn has lots of useful methods, e.g., newValue(int), which will in fact return an IJavaPrimitiveValue.

cheers,
Stephan
Re: JDT Debug Tools Help [message #895445 is a reply to message #895194] Fri, 13 July 2012 00:28 Go to previous messageGo to next message
Matt R is currently offline Matt RFriend
Messages: 6
Registered: July 2012
Junior Member
Thank you for all your help. I have finally succeeded in doing what I want.

Re: JDT Debug Tools Help [message #1367002 is a reply to message #895445] Mon, 19 May 2014 15:31 Go to previous messageGo to next message
diego loro is currently offline diego loroFriend
Messages: 2
Registered: May 2014
Junior Member
Hi Matt,

can you please detail the way in which you finally solved the problem?
I would be really interested in the details about the sendMessage() arguments approach.
If you want to attach the code starting from the JDIstackframe till the sendMessage call it would be wonderful!

Thanks in advance,
Diego
Re: JDT Debug Tools Help [message #1368846 is a reply to message #1367002] Tue, 20 May 2014 09:51 Go to previous message
diego loro is currently offline diego loroFriend
Messages: 2
Registered: May 2014
Junior Member
Hi Matt,

we solved the problem too.
For next programmers that will have the same problem here is our solution:

IValue value = javaVariable.getValue();
if(value instanceof IJavaObject) {
	IJavaObject object = (IJavaObject) value;
	IJavaThread thread = getThread();
	if(thread == null)
		throw new DebugException(null);
        // STRING VALUE
	IJavaValue result = object.sendMessage("toString", "()Ljava/lang/String;", new IJavaValue[] { }, thread, false);
        // BYTE VALUE
        // IJavaValue resultBytes = object.sendMessage("getBytes", "()[B", new IJavaValue[] { }, thread, false);

	variableValueString = formatString(result.toString());
}


private static IJavaThread getThread() {
	IJavaStackFrame stackFrame = getStackFrame();
	return (IJavaThread) stackFrame.getThread();
}


private static IJavaStackFrame getStackFrame() {
	IAdaptable adaptable = DebugUITools.getDebugContext();
	if(adaptable != null)
	return (IJavaStackFrame) adaptable.getAdapter(IJavaStackFrame.class);
	else
	return null;
}


Thanks all,
best regards
Previous Topic:Default Java compiler settings
Next Topic:How do you disable Java Update on Mac OS X Mavericks 10.9.2?
Goto Forum:
  


Current Time: Sat Nov 09 03:17:27 GMT 2024

Powered by FUDForum. Page generated in 0.03751 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top