Can't breakpoint the last statement of a code block in Eclipse - java

if (true) {
String a = "foo";
String b = "bar";
}
If I set a breakpoint at String a = "foo"; eclipse will stop, and I can step over and see the value of a inside the variables window. But I can't step over the 2nd statement, it just leaves the code block and I never see the value of b.
This forces me to add a noop statement after String b = "bar"; just so I can see what b contains. I also can't add a breakpoint on the closing } which I think are maybe related issues.
I know Visual Studio allows this, so is there a way to do this in Eclipse?

To set a breakpoint at the end of an arbitrary block is not possible (without byte-code hacking).
If it is a method body, then it is possible: you can set a Method breakpoint. Do this by double-clicking on the method definition line:
(notice the little arrow?) and then in the breakpoints view, select the breakpoint to see both an Entry and an Exit option tick-box in the displayed properties:
The little arrow indicates that, by default, we have set a breakpoint on entry to the method.
Now select Exit (and deselect Entry) and you will see this in the breakpoints view:
(There is a different little arrow, indicating an exit breakpoint.)
Now run the debugger on this little breaker ('Debug As a Java Application') and it will stop on the exit brace of the method:
and the local variables (only a in this case) are now visible (with the correct values) in the Variables view:
It is worth noticing that this type of breakpoint traps method exit however this happens -- even, for example, if we exit by throwing an exception.

You can highlight the expression on the right hand side of the assignment and press Ctrl+Shift+I (for 'inspect' I think). It will evaluate the expression and give you the result. That way you can know the value of b without needing a breakpoint after the assignment.

I'm honestly not sure what's going on in your Eclipse installation. I'm working in Java and just tried everything I can think of. I checked a static method for breakpoint on the last line that is not a } and it works just fine. I checked the same for a non-static method.
It breaks down this way: you can't breakpoint on a curly brace end, but it will default to whatever is under the curly brace, line-wise. So if you have a nested function:
public int DoesStuff(int x, int y) {
if(x > y) {
DoThing;
}
else {
DoOtherThing;
}
}
Then the last two braces cannot be break-pointed, but DoThing and DoOtherThing can. Make sense?

If ending statement is assignment and it is on local variable why do you want to see its value because it will not be in scope anymore and can't effect.
If it's setting same class attribute then you can see it when you return from this call and you have the object on which this method operated.
Although this doesn't answer the question but I am trying to understand the use-case of your problem.

Related

Java methods - what RETURN actually means?

I'm pretty certain I'm missing something really obvious here but this seems quite bizarre.
I'm developing for Android using Eclipse - and I have a method similar to which I'm debugging and it's doing something rather odd...
public boolean test() {
if (variable == value)
return true;
// more code appears here
return false;
}
Stepping through that, on the first line (the if statement) the debugger suggests that variable does indeed equal value (they've both byte variables with a value of 0) - the debugger then moves onto the 2nd line (the return true) but it then moves on to the last line (return false) - skipping everything inbetween!?
The value returned was 'false'
WTF is going on there? I'd assumed that RETURN would exit the method entirely - but the debugger (and the return value being sent back - being false) suggests that it does nothing of the sort!?
What am I missing which is staring me in the face? Are return statements as the last line of methods always executed or something?
p.s. interesting update...
The variables I'm using are assigned in code which I didn't write - I just dug-out the source and re-built/re-ran the debugger with access to that source and I found this line in it
byte variable = (byte)9;
Can you see anything wrong with that and would that perhaps explain the problem do you think!? I've emailed the author but meanwhile - erm....
Update2
OK, I've completely remade the project, cleaned and rebuilt it, uninstalled and reinstalled it into the phone and the debugger now behaves more sensibly...
The problem is clearly the use of '9' (they use 0-9 as possible values in a byte!!) - what's happened now is that although the debugger is suggesting 'variable' is "0" - it's also failing comparison to (byte)0 and thus I get a 'false' return - which is actually correct.
I'm obviously stuck until they change their code to use a short - as for accepting an answer, it's tricky as the 'rebuild everything' answers and the 'compare using (byte) or bytevalue()' answers were sort-of both right!?
If they are Byte objects allocated with new, then == will test if they are the same object in memory and return false. Try to use:
variable.byteValue() == value.byteValue()
instead.
I think your problem is that, when you use the Byte object, doing the == is not comparing the VALUES of the bytes, but is instead comparing the object in memory. This is similar to how String works.
Instead, try:
public boolean test() {
if (variable.equals(value))
return true;
// more code appears here
return false;
}
Update based on Comment
If you are comparing two bytes (particularly a variable and a value), make sure you are casting to a byte on both values (see Binary Numeric Promotion as to why). So, try:
public boolean test() {
if ((byte)variable == (byte)value)
return true;
// more code appears here
return false;
}
I don't think your code buffer in eclipse is matching what is being debugged. The only time you should see code execute past a return statement is of you are using a finally block, in which you will see the code execute in the finally block after the return statement in the debugger.
Are return statements as the last line of methods always executed or
something?
No.
Try surrounding your if block in {} and then see what happens.
Your description of your code does not match the code you pasted. I suspect that this is a symptom of the real problem: you are stepping through source code that is not the same as your compiled code. The line numbers don't match. So it looks like it's doing all kinds of wacky things. Rebuild your compiled code and debug again.
Logically, a return statement does immediately exit a method--
But before it does, other things might happen, like a finally statement after an enclosing try block.
Usually, the debugger will skip to the closing brace of a method after the return statement, rather than to the last return statement.
This makes me think there is something unusual with your method, or that the method you are seeing in the debugger is not identical to the method that is running on the device.
It shouldn't be doing it and what you know about return already is correct.
This could happen when the compiled binary is different than the source code. Try cleaning your project and rebuilding it.
You could try remove "more code appears here" and add this code line-by-line, until you find mistake. Also try restart eclipse, clean up project and redeploy application.
This behavior is normal using the Eclipse debugger. I recommend you to watch the value returned by the method itself and not the code being executed (it will be true, not false).
For example, try the following code. You will see that return true is reached, but later foo, and foo2 are not initialized (although it seems to reach return false).
public boolean test() {
if (variable == value)
return true;
int foo = 5;
int foo2 = 7;
// more code appears here
return false; }
I don't see an open bracket after your "if" statement. It should look like this:
public boolean test() {
if (variable == value) {
return true;
// more code appears here
}
return false;
}
With the additional brackets the "true" will only be associated with the IF conditions, and the false will be only if the IF conditions are not satisfied.

Break from other class possible?

I recently rediscovered the use of breaking back to a label. Now I'm wondering if it is possible to break back to a label from another class.
Example of what i want:
Main.class
label:
for (Product p : ProductList) {
if (p.getSet() == true) {
classHandler();
}
}
Classhandler.class
someFunction() {
break label;
}
While I was typing this I actually tried making a local function in my Main class (so I could just call that function instead) but even there I got the undefined label: label error.
No, you can't. And you shouldn't.
If the condition for breaking is some problem, then throwing an exception would be the correct approach.
Otherwise you should do something like returning a flag that indicates if other products should still be handled and reacting on that in your loop.
As you noticed you can't even break through method-borders, and that's a good thing. break and continue are powerful tools, but can easily make your code confusing, if used in the wrong way. For example a break hidden inside a huge code block can be easy to miss, but if you use a continue at the very top of a method to skip an iteration based on some condition, then the intention is pretty clear.
The label that you break to must be in scope. From the java sun documentation:
A break statement with label Identifier attempts to transfer control
to the enclosing labeled statement (§14.7) that has the same
Identifier as its label; this statement, which is called the break
target, then immediately completes normally. In this case, the break
target need not be a while, do, for, or switch statement. A break
statement must refer to a label within the immediately enclosing
method or initializer block. There are no non-local jumps
No, you cannot. That does not even work between two methods of the same class. Labels are scoped (at the most) within a single method.
It doesn't make sense, since there is no guarantee that label exists, not even that someFunction() is called within a loop.

Java Compiler: Stop complaining about dead code

For testing purposes, I often start typing some code in an already existing project. So, my code I want to test comes before all the other code, like this:
public static void main(String[] args)
{
char a = '%';
System.out.println((int)a);
// To know where '%' is located in the ASCII table.
// But, of course, I don't want to start the whole project, so:
return;
// The real project starts here...
}
But the compiler complains about the return-statement, because of the following "dead code". (While in C++ the compiler obeys the programmer and simply compiles the return statement)
To prevent the compiler complains, I write a stupid if-statement:
if (0 != 1) return;
I hate it. Why can't the compiler do what I ask? Are there some compilation flags or annotations or whatever to solve my problem?
Thanks
There are no flags to turn of this behaviour. The rules that make dead code a compile time error are part of the JLS (§14.21 Unreachable Statements) and can't be turned off.
There's an explicit loophole in the loop which allows code like this:
if (true) return;
someOtherCode(); // this code will never execute, but the compiler will still allow it
This is done explicitly to allow "commenting-out" or conditional compilation (depending on some static final boolean flag).
In case you're curious: the loophole is based on the fact that a known-constant value of the condition expression of an if statement is not considered when checking reachability of code within or after the if statement. A similar situation occurs with while, where known-constant values are considered, so this code will not compile:
while (true) return;
someOtherCode(); // this will be flagged as an unreachable statement
You shouldn't have lots of dead cod ein your project however two ways I get around this for prototyping.
Use /* */ to comment out the code.
// But, of course, I don't want to start the whole project, so:
/*
// The real project starts here...
*/
}
or create a second method.
// But, of course, I don't want to start the whole project, so:
// realProject();
}
public static void realProject()
// The real project starts here...
}

How do I create a breakpoint at a specific place without there being any code after it

I am creating breakpoints to debug my java application , and am using netbeans 6.8 (if this is relevant).
Basically the problem I have is that when I set a breakpoint and debug the program will break before it executes the code at that line. So for example if I have the following.
public static void someMethod() {
Object iWantToInspectThis = someOtherMethod();
if(somethingThatIsFalseInThisCase == true)
{
doSomethingElse();
}
}
So , I want to set a watch on iWantToInspectThis object and then break after it is set to the return value of someOtherMethod() so I can see what it is set to.
But if I set a breakpoint on that line then I will not see the result of this line being executed, and I cannot set the breakpoint later (inside the if statement) because then it will not be reached.
The only way I can manage to do this is to add a useless line like System.out.println("this is pointless"); after the call and break there instead which seems like a stupid way to have to do it.
How does everybody else deal with this?
Put a break on that line, and use step into next line (F8 if i remember correctly) so the line executes, and then you can see the value by hovering the mouse into the variable, or using a watch.

eclipse beakpoint: stop before leaving a Java method

Is there a way to tell the debugger to stop just before returning, on whichever statement exits from the method, be it return, exception, or fall out the bottom? I am inspired by the fact that the Java editor shows me all the places that my method can exit - it highlights them when you click on the return type of the method declaration, (Mark Occurrences enabled).
[eclipse 3.4]
Put a breakpoint on the line of the method signature. That is where you write
public void myMethod() {
Then right-click on the breakpoint and select "Breakpoint Properties". At the bottom of the pop-up there are two checkboxes: "Method Entry", "Method Exit". Check the latter.
You can set a method breakpoint.
Double click in the margin next to the method declaration. A breakpoint with an arrow decoration appears. Right-clicking to examine the properties, you can set "Suspend on:" for "Method Entry" and/or "Method Exit".
You can read more about them in the Eclipse Cookbook.
Good question. Off the top of my head, I'd do this:
public void method(Object stuff) {
try {
/* normal code */
} finally {
int x = 0;
}
}
You can set the breakpoint on the x = 0 line, and it will ALWAYS be executed no matter where you return. Even with an exception being thrown, it will be run.
The catch to this is scope. Unless you define variables outside of the try block, you won't be able to see their values where you get to the finally block since they will have exited scope.
Having to just place 5 breakpoints (one for each return statement, whatever) may work best.
I hope there is a better way, I'd love to know it.

Categories