tags:

views:

350

answers:

3

Greetings,

I'm using embedded java, I write the application to a low resource device. One of the problems I get is when the code crashes the device stops. I can get a little information from it with some logging that I've added. (Simple print statements)

This logging cannot remain in the application due to memory constraints.

I was wondering does anyone know is there a flag I can pass to the JVM to state if its a debug or standard compilation I require.

I'd like for the print statements to be included if its a debug build, if it is a standard build to remove the print statements. I ask because I've to constantly cut and paste the statements etc. (IT's a pain)

Thanks

+1  A: 

Well, you'll have to use a pre-processor, and still it would be a kind of ugly.

Just pre-process your source before compilation. Using cpp, for example.

It is said that javac sometimes might drop statements in dead condition branches, including static final booleans, like

private static final DEBUG = false;

if(DEBUG) System.err.println("Entered");

But I'm not sure, I advise you to try that and check if bytecode contains that call.

alamar
+4  A: 

You can make use of the fact that if (constant) is optimized by the compiler.

Make a global variable somewhere called DEBUG:

public static final boolean DEBUG = true;

and then do your logging like so:

if (DEBUG) {
    System.out.println("Debug");
}

To disable debugging, simply change DEBUG to false, and all of the logging statements will be optimized away by the compiler. You can verify this by looking at the generated bytecode with javap -c.

For example:

class DebugTest {
    public static final boolean DEBUG = true;
    public static void main(String[] args) {
        if (DEBUG) {
            int a = 10;
            System.out.println("a = " + a);
        }
    }
}

is compiled as:

Compiled from "DebugTest.java"
class DebugTest extends java.lang.Object{
public static final boolean DEBUG;

DebugTest();
  Code:
   0:   aload_0
   1:   invokespecial #1; //Method java/lang/Object."":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   bipush 10
   2:   istore_1
   3:   getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   6:   new #3; //class java/lang/StringBuilder
   9:   dup
   10:  invokespecial #4; //Method java/lang/StringBuilder."":()V
   13:  ldc #5; //String a = 
   15:  invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   18:  iload_1
   19:  invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   22:  invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   25:  invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   28:  return

}

Changing DEBUG to false yields:

Compiled from "DebugTest.java"
class DebugTest extends java.lang.Object{
public static final boolean DEBUG;

DebugTest();
  Code:
   0:   aload_0
   1:   invokespecial #1; //Method java/lang/Object."":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   return

}
Michael Myers
+1  A: 

Is the issue that the logging statements must be removed from the standard release, or just that they cannot be enabled?

If it's only the latter, than simply wrap your log statements in an if-check as the other answers have mentioned.

Whatever you do, don't continue copy/pasting your code in and out of the project - automate that manual work. Save yourself time.

matt b