Remove if(debug) intructions from Java bytecode with a static flag

One of the several techniques (a MacGyver style) for debug in Java is insert if(DEBUG) messages for monitoring errors and events. However, according to the size of your code, the number of conditional tests performed to check if the DEBUG flag was enabled can affect the performance of your application.

In C one of the alternatives is to use #define DEBUG directive jointly with #ifdef DEBUG tests, hence, according to this flag, compiler will inserts or not the debug code in the executable.

In Java you can do that using a static flag, for instance, considers the example as follows:

class Teste{

        public static final boolean DEBUG = true;

        public static void main( String[] args ){

                if( DEBUG ){
                        int a = 10;
                        System.out.println( "a = " + a );
                }
        }
}

Compiling the code:

$ javac Teste.java

Verifying the generated bytecode to check the if(debug) instructions:

$ javap -c Teste.java

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

Teste();
  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 the debug flag to false:

class Teste{

        public static final boolean DEBUG = false;

        public static void main( String[] args ){

                if( DEBUG ){
                        int a = 10;
                        System.out.println( "a = " + a );
                }
        }
}

Recompiling the code:

$ javac Teste.java

Verifying again the generated bytecode we can see that compiler take in account that since the debug flag is constant (final) its value cannot be changed during the execution so the conditional test will always returns false and can be removed.

$ javap -c Teste.java

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

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

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

}

See ya

One Response to Remove if(debug) intructions from Java bytecode with a static flag

  1. Eduardo says:

    Legal este, Mano. Não sabia que tinha como fazer isto.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: