3

Below is a snippet of my code:

class A { 

   private boolean debug = false;

   // Called when server boots up.
   public void init (property) { 
      debug = property.getBoolean ("debug_var"); // read debug from a config file.
   }

   // some other function  
   public void foo () { 
       if (debug) { 
                 System.out.println ("From inside the debug block");
       }
   }
 }

When I run the code, if (debug) actually prints out "From inside debug block" if debug == true in the config file.

Two Questions:

  1. So, in this case does the compiler include the if block in the .class file just because the value of variable debug might change on run time?

  2. If this is true, then how can I eliminate some code from being added to the .class file on certain environments?

FSP
  • 4,677
  • 2
  • 19
  • 19

6 Answers6

5

If you must do something like this, most logging frameworks have their own means of setting the level of log detail, and they just don't output any log statements that are too low-level at runtime. Use a logging framework to do this properly.

For example, with the built-in java.util.logging framework, you'd do something like

Logger.getLogger("ThisClass").log(Level.FINE, "Log message");

which only gets printed when the log level is set to FINE or below, but is ignored when the log level is CONFIG or lower.

"Conditional compilation" isn't a thing that makes sense in Java in general, but with some care, the JIT will optimize away branches it can determine will never be executed.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1

As others have pointed out, a Java compiler is typically quite naive, and just translates what you have as Java source code, into Java bytecode. For example, an if statement is most often translated to a conditional branch, whether or not you may find it evident that the branching condition is always false.

From a theoretical perspective however, there's nothing that prevents a compiler to figure out that certain branches can never be taken, and simply omit them in the bytecode. Nothing in the Java Language Specification dictates how something should be compiled when targeting bytecode.

aioobe
  • 413,195
  • 112
  • 811
  • 826
1

The closest you can come is by using a static variable, which is useless (essentially) at run-time.

However, in your example, the JVM will likely optimize it away after it's been run enough times, so if your concern is run-time efficiency, it's likely not worth worrying about.

Ultimately I'd ask why you want to remove code from the class file based on an environment--if it's not something that can change at run time then your best option would be to create some form of pluggable implementation that can be determined/injected at runtime.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • The reason why I want some code to be removed is because in development env. I have some gaffe's which I do not want to be available in production. Can you elaborate a bit on developing pluggable implementation that you mentioned or can you point to some good resources. Thanks. – FSP Jun 12 '12 at 00:12
  • @FSP Well... I'd fix the code or make it configurable. I don't see any real reason to remove it from the *class* file, but your situation isn't clear. By "pluggable" I mean "in this environment, use this implementation"--there are a ton of ways to do this, most revolve around *some* form of dependency injection/inversion of control, so I'd aim at that first. – Dave Newton Jun 12 '12 at 00:16
0

There is nothing like conditional compilation (Unless java finds a condition which is guaranteed to be NOT executed). Your class file contains byte code equal of whatever you have in Java file.

EDIT: As aiobee pointed, compiler may omit branching statements if it finds them as not to be executed.

kosa
  • 65,990
  • 13
  • 130
  • 167
  • Nothing prevents a compiler from omitting branches as long as they are guaranteed not to be executed. – aioobe Jun 11 '12 at 19:12
  • :-) Well, now your answer is somewhat contradictory (or you and I have different definitions of conditional compilation.) – aioobe Jun 11 '12 at 19:15
  • I think it is perspective of defining "conditional". – kosa Jun 11 '12 at 19:19
0
  1. Yes, the compiler will include this in the .class file.
  2. There is no mechanism for conditional compilation. You could emulate some of it by using a compiler plugin (in JDK 1.7 and higher), or you could try to achieve similar effects by using bytecode manipulating techniques like AspectJ.
Jochen
  • 2,277
  • 15
  • 22
  • Neither 1 nor 2 is guaranteed by the spec. (So technically speaking the answer is wrong.) – aioobe Jun 11 '12 at 19:14
  • What? The compiler is not permitted to remove reachable code. It can optimize away the conditional under some conditions, but the print statement must be there. That is in the spec! And for 2, there is nothing in the language spec that permits conditional compilation. So how is my answer wrong? – Jochen Jun 11 '12 at 19:29
0

It used to be that if you declared a boolean as static and final and set its value to false, that the compiler would elide the code. That was the original Java compiler though. I don't know if the current one does this or not though (the current one has been around for a long time now). The rationale behind this was to allow you to make your applet downloads smaller. It was a klunky mechanism at best so not widely used.

To test this, change your debug var to private static final boolean debug=false; compile it, save the class file, then flip it to true. Then compile it again and see if the class files are different. BTW, your init function won't work when debug is declared as final.

BillRobertson42
  • 12,602
  • 4
  • 40
  • 57