Java Compiler: Stop complaining about dead code - java

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...
}

Related

Is this some genius thing or simple just bad code?

This is a code snippet I found in an open source Java templating project.
Does anyone have a clue what this construct may be good for?
final public Expression Expression() throws ParseException {
Expression exp;
exp = OrExpression();
{if (true) return exp;}
throw new Error("Missing return statement in function");
}
This is sloppy code. The actual effect is simply return OrExpression();.
There is one excuse that I accept for code like this: There are lots of other methods like it, which follow a similar pattern but are more complex such that the useless bits here are not useless. This is a bit of an extreme example, however.
However, there is almost no excuse for the throw new Error("Missing return statement in function");. The Java compiler will refuse to compile a method whose return type is not void and which has a code path which reaches the end (does not return, throw, or enter an infinite loop). The only reason this would be a good idea is if the intent was to permit incomplete code to compile — i.e. fail at run time rather than compile time so that other parts of the code can be used or tested — but even then applying it to all methods is a bad idea.
This is an automatically generated code from JavaCC.

Unreachable code compiler error [duplicate]

This question already has answers here:
Why does Java have an "unreachable statement" compiler error?
(8 answers)
Closed 6 years ago.
The following code gives an unreachable statement compiler error
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
Sometimes for testing purposes a want to prevent a method from being called, so a quick way to do it (instead of commenting it out everywhere it's used) is to return immediately from the method so that the method does nothing. What I then always do to get arround the compiler error is this
public static void main(String[] args) {
if (true) {
return;
}
System.out.println("unreachable");
}
I'm just curious, why is it a compiler error?? Will it break the Java bytecode somehow, is it to protect the programmer or is it something else?
Also (and this to me is more interesting), if compiling java to bytecode does any kind of optimization (or even if it doesn't) then why won't it detect the blatant unreachable code in the second example? What would the compiler pseudo code be for checking if a statement is unreachable?
Unreachable code is meaningless, so the compile-time error is helpful. The reason why it won’t be detected at the second example is, like you expect, for testing / debugging purposes. It’s explained in The Specification:
if (false) { x=3; }
does not result in a compile-time error. An optimizing compiler may
realize that the statement x=3; will never be executed and may choose
to omit the code for that statement from the generated class file, but
the statement x=3; is not regarded as "unreachable" in the technical
sense specified here.
The rationale for this differing treatment is to allow programmers to
define "flag variables" such as:
static final boolean DEBUG = false;
and then write code such as:
if (DEBUG) { x=3; }
The idea is that it should be possible to change the value of DEBUG
from false to true or from true to false and then compile the code
correctly with no other changes to the program text.
Reference: http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
Its because the compiler writer assumed that the human at the controls is dumb, and probably didn't mean to add code that would never be executed - so by throwing an error, it attempts to prevent you from inadvertently creating a code path that cannot be executed - instead forcing you to make a decision about it (even though, as you have proven, you still can work around it).
This error is mainly there to prevent programmer errors (a swap of 2 lines or more). In the second snippet, you make it clear that you don't care about the system.out.println().
Will it break the Java bytecode somehow, is it to protect the programmer or is it something else?
This is not required as far as Java/JVM is concerned. The sole purpose of this compilation error is to avoid silly programmer mistakes. Consider the following JavaScript code:
function f() {
return
{
answer: 42
}
}
This function returns undefined as the JavaScript engine adds semicolon at the end of the line and ignores dead-code (as it thinks). Java compiler is more clever and when it discoveres you are doing something clearly and obviously wrong, it won't let you do this. There is no way on earth you intended to have dead-code. This somehow fits into the Java premise of being a safe language.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
says:
14.21. Unreachable Statements
It is a compile-time error if a statement cannot be executed because it is unreachable.
Example 1:
In this case you are return before any statement because of it compiler never going to execute that code.
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
In second code I have put the statement above of return and its work now :)
Example 2:
public static void main(String[] args) {
System.out.println("unreachable"); // Put the statement before return
return;
}
The reason behind this is that if you return sometime then code after it never going to execute because you already return the function data and as so it is shown unreachable code.
It's because it's a waste of resources for it to even be there. Also, the compiler designers don't want to assume what they can strip out, but would rather force you to remove either the code that makes it unreachable or the unreachable code itself. They don't know what is supposed to be there. There's a difference between the optimizations where they tweak your code to be a bit more efficient when it's compiled down to machine code and blatantly just removing code "you didn't need."

Java If(false) Compile

I am developing a dynamic web project using Tomcat. It is useful to have a global flag that is the only thing I have to change between my development and deployment servers. The biggest use of the flag is with print statements.
public class Debug {
public final static boolean DEVEL = true;
public static void print(String message){
if(DEVEL){
System.out.println(message);
}
}
}
My question is, will java compile out the print statements. i.e. if the devel tag is false, the messages will obviously not print but will they be included in the class files (devel is final). This is a question of efficiency. I've heard that the java compiler is very smart but will it pick up on this.
use the 'final' attribute (as you did), and it will compile out the code:
public static final boolean DEVEL = false;
You can check by grepping the resultant class file for a string that would appear only if the code were compiled.
Take a look into this article:
http://www.javaworld.com/javaworld/jw-03-2000/jw-03-javaperf_4.html
The code you presented is called a "dead code" so it will not be included in the compiled class file if you set DEVEL to false it will not be included in the bytecode.
Also, check the command
javap -c
to see the resulting bytecode of your class.
If you want to have the compiler not compile it out, use this:
public final static boolean DEVEL = Math.random() > -1;
The compiler won't know that this is always true. (of course use < -1 for false)
I find this trick handy when you want to remove code temporarily without having the compiler complain abut dead code, eg:
void myMethod() {
// temporarily exit early
if (Math.random() > -1) return;
// usual code
}
I have never seen the compiler remove code like this, however the JIT will effectively remove code which never runs. Assertions is a common use case for this. There may still be a notional cost but generally one not worth worrying about. i.e. less than 1 nano-second.
The cost can be greater if the toString() method of the message is costly. The toString method of a large sql query in a prepared statement caused a heap overflow due to this line. Thus the standard did not remove it.

using labels in java without "loops"

I always thought that the labels must be used only with loops but it seems not. Giving such code:
public class LabelTest {
public static void main(String[] args) {
label1: System.out.println("");
label2: LabelTest t = new LabelTest();
}
}
When compiled line labeled "label1" compiles but the code at "label2" gives errors. Why's that? And why would I want to label statements which are not "loops"?
You get an error because a label cannot be applied to variable declarations, that's just how the language grammar is defined (a label can only precede a Statement, and a LocalVariableDeclarationStatement is not a Statement). The reason is probably that it could cause confusion concerning variable scope. This works:
label1: System.out.println("");
label2: { LabelTest t = new LabelTest(); }
To add to Michael Borgwardt's answer, you can do things like this for convenience (I just discovered this the other day while reading through the Java rt.jar source code):
BlockSegment:
if (conditionIsTrue) {
doSomeProcessing ();
if (resultOfProcessingIsFalse()) break BlockSegment;
otherwiseDoSomeMoreProcessing();
// These lines get skipped if the break statement
// above gets executed
}
// This is where you resume execution after the break
anotherStatement();
Now, this is logically equivalent to:
if (conditionIsTrue) {
doSomeProcessing ();
if (!resultOfProcessingIsFalse()) {
otherwiseDoSomeMoreProcessing();
// More code here that gets executed
}
}
anotherStatement();
But, you get to skip some of the extra braces (and indentations that come with braces). Perhaps it looks cleaner (it does in my opinion), and there are some places where this style of coding may be appropriate and less confusing.
So, you may use labels beyond just loops, and even beyond if statements. For example, this is valid Java syntax (and maybe you could conjure up a reason to do something like this):
statementOne();
statementTwo();
BlockLabel: {
statementThree();
boolean result = statementFour();
if (!result) break BlockLabel;
statementFive();
statementSix();
}
statementSeven();
If the break gets executed here, then execution skips to the end of the block denoted by the label, and statementFive() and statementSix() get skipped.
The usefulness of this style (without an if statement) becomes more evident when you have blocks within blocks where you must skip around. In general, you can accomplish everything with smart enough use of loops. However, there are a few cases where labels without loops make for easier reading of code. For example, if you need to sequentially check parameters, you may either do this or throw an exception. It ends up being a matter of cleanliness of code and personal style.
It does not compile. Good question!
I have just played a little bit with your code snippet. It seems that compiler expects method call or operator after label. It does not allow assignment at this point.
I think that the fact that label is not forbidden before operators other than for, while and do is probably a bug (?!) of java compiler of specification. Anyway it is not so critical. It does not bother me (personally).
Java syntax is based on C syntax.
In C you can put a label anywhere (not just on loops) and then use goto to jump the execution to that line. Now, goto wasn't implemented in Java, but labels were left so that they can be used in combination with break or continue.
It's not that important since this isn't a standard use of labels anyway. Using labels with continue or break is bad enough (most of the times). Using them freely is also useless.
I am little late to answer this. Anyway,
label2: LabelTest t = new LabelTest(); -> Doesn't work because it is a declarative statement, as most of the above comments state the same. To make it work just do the following:
label2: new LabelTest(); // works fine
Refer to Lable in JLS

Does Java recognize infinite loops?

Given the following code sample:
public class WeirdStuff {
public static int doSomething() {
while(true);
}
public static void main(String[] args) {
doSomething();
}
}
This is a valid Java program, although the method doSomething() should return an int but never does. If you run it, it will end in an infinite loop. If you put the argument of the while loop in a separate variable (e.g. boolean bool = true) the compiler will tell you to return an int in this method.
So my question is: is this somewhere in the Java specification and are there situation where this behavior might be useful?
I'll just quote the Java Language Specification, as it's rather clear on this:
This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, instance initializer or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
...
A while statement can complete normally iff at least one of the following is true:
The while statement is reachable and the condition expression is not a constant expression with value true.
There is a reachable break statement that exits the while statement.
...
Every other statement S in a nonempty block that is not a switch block is reachable iff the statement preceding S can complete normally.
And then apply the above definitions to this:
If a method is declared to have a return type, then every return statement (§14.17) in its body must have an Expression. A compile-time error occurs if the body of the method can complete normally (§14.1).
In other words, a method with a return type must return only by using a return statement that provides a value return; it is not allowed to "drop off the end of its body."
Note that it is possible for a method to have a declared return type and yet contain no return statements. Here is one example:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Java specification defines a concept called Unreachable statements. You are not allowed to have an unreachable statement in your code (it's a compile time error). A while(true); statement makes the following statements unreachable by definition. You are not even allowed to have a return statement after the while(true); statement in Java. Note that while Halting problem is undecidable in generic case, the definition of Unreachable Statement is more strict than just halting. It's deciding very specific cases where a program definitely does not halt. The compiler is theoretically not able to detect all infinite loops and unreachable statements but it has to detect specific cases defined in the spec.
If you are asking if infinite loops can be useful, the answer is yes. There are plenty of situations where you want something running forever, though the loop will usually be terminated at some point.
As to your question: "Can java recognized when a loop will be infinite?" The answer is that it is impossible for a computer to have an algorithm to determine if a program will run forever or not. Read about: Halting Problem
Reading a bit more, your question is also asking why the doSomething() function does not complain that it is not returning an int.
Interestingly the following source does NOT compile.
public class test {
public static int doSomething() {
//while(true);
boolean test=true;
while(test){
}
}
public static void main(String[] args) {
doSomething();
}
}
This indicates to me that, as the wiki page on the halting problem suggests, it is impossible for there to be an algorithm to determine if every problem will terminate, but this does not mean someone hasn't added the simple case:
while(true);
to the java spec. My example above is a little more complicated, so Java can't have it remembered as an infinite loop. Truely, this is a weird edge case, but it's there just to make things compile. Maybe someone will try other combinations.
EDIT: not an issue with unreachable code.
import java.util.*;
public class test {
public static int doSomething() {
//while(true);
while(true){
System.out.println("Hello");
}
}
public static void main(String[] args) {
doSomething();
}
}
The above works, so the while(true); isn't being ignored by the compiler as unreachable, otherwise it would throw a compile time error!
Yes, you can see these 'infinite' loops in some threads, for example server threads that listen on a certain port for incoming messages.
So my question is: is this somewhere in the Java specification
The program is legal Java according to the specification. The JLS (and Java compiler) recognize that the method cannot return, and therefore no return statement is required. Indeed, if you added a return statement after the loop, the Java compiler would give you a compilation error because the return statement would be unreachable code.
and are there situation where this behavior might be useful?
I don't think so, except possibly in obscure unit tests.
I occasionally write methods that will never return (normally), but putting the current thread into an uninterruptible infinite busy-loop rarely makes any sense.
After rereading the question....
Java understands while(true); can never actually complete, it does not trace the following code completely.
boolean moo = true;
while (moo);
Is this useful? Doubtful.
You might be implementing a general interface such that, even though the method may exit with a meaningful return value, your particular implementation is a useful infinite loop (for example, a network server) which never has a situation where it should exit, i.e. trigger whatever action returning a value means.
Also, regarding code like boolean x = true; while (x);, this will compile given a final modifier on x. I don't know offhand but I would imagine this is Java's choice of reasonable straightforward constant expression analysis (which needs to be defined straightforwardly since, due to this rejection of programs dependent on it, it is part of the language definition).
Some notes about unreachable statements:
In java2 specs the description of 'unreachable statement' could be found. Especially interesting the following sentence:
Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
So, it is not obviously possible to exit from while (true); infinite loop. However, there were two more options: change cached values or hack directly into class file or JVM operating memory space.

Categories