Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I watch private fields of other objects directly in the IDE when debugging?

Tags:

java

eclipse

C# is the language I am most comfortable with but do Java when at work. I guess you can say I am very comfortable with using the Visual Studio IDE. One of the things I enjoyed about its debugger is that I can put watch variables ("Expressions" in Eclipse) for any expression. So I could take a peek at values of specific fields public or non-public, call methods, etc. with no problem as I am debugging.

It doesn't seem like I can do the same in Eclipse. I have to resort to calling the associated getter method for the field (assuming it has one). If it doesn't have one, I either have to temporarily add one so I can view it and remember to remove it when I'm done or I'm just SOL.

How can I put a watch expression for an object on one of its private fields? Or am I just doing it wrong and I have to craft special expressions to view them?
(Or is there a better way for me to get the information that I want?)

e.g.,

I have an HttpServletRequest and want to keep an eye on the requestURI. If I just watch the request variable, it lists a lot of its fields and it's just too much information. I'm only interested in one thing in the object so to minimize this, I want to add a watch expression for that one thing.

The field name is apparently requestURI so I added the expression: request.requestURI. Eclipse throws an error saying it's not a field (it is, it's just not public). Instead of going directly to the field, I had to go to the getter: request.getRequestURI() and that works fine. But I can't always count on the getter being available.

the variables view
The Variables view

the expressions view
The Expressions view

like image 917
Jeff Mercado Avatar asked Feb 15 '12 22:02

Jeff Mercado


3 Answers

The Eclipse evaluates expression considering the private/protected fields of Declared Type, not of Actual Type.

Example:

Number n1 = new Integer(1000);
Integer n2 = new Integer(1000);

Expressions:

n1.value  can't be evaluate
n2.value  returns 1000, perfectly

An alternative is use DetailFormatter (right-click in variable > New Detail Formatter).

The Eclipse will use this expression instead of toString() method when the textual representation of a object of type is displayed (in Variables View, for example).

Your DetailFormatter (for ApplicationHttpRequest) can be:

requestURI 

or

"URI: " + requestURI + "\n" +
"Path: " + servletPath
like image 144
João Paulo G. Brandt Avatar answered Sep 18 '22 20:09

João Paulo G. Brandt


Doesn’t matter if the field is private or protected, eclipse expressions will evaluate correctly. But the scope of variable matters.

Correct me if i am wrong.

requestURI is a protected field in org.apache.catalina.core.ApplicationHttpRequest which implements HttpServletRequest. In your case variable request is of type HttpServletRequest and you are trying to access HttpServletRequest.requestURI and this field Doesn’t exist and eclipse fails. I think it's normal. May be if you do proper casting, expression will evaluate correctly.

like image 30
titogeo Avatar answered Sep 17 '22 20:09

titogeo


Writing an expression in the Expressions view evaluates just as if you had written a line of code, and just executed it prior to the currently highlighted line. There is one difference that I know about (probably others to, but this is the important one) which is that you can bypass the class accessor visibility restrictions, and see private, protected and default members that the current stack frame perhaps couldn't.

That said the expression does require you to have the correct kind of reference. If you inserted this line in to code, the java compiler would complain that requestURI is not a field of HttpServletRequest. And therefore, you need to cast to the class (or subclass of) that actually declares the field: ApplicationHttpRequest.

Now, why they didn't bother exposing the same magic in Expressions as they do in Variables where as you point out they list ALL members of the concrete class even if the declared type wouldn't show them, I couldn't say.

like image 44
sharakan Avatar answered Sep 21 '22 20:09

sharakan