简体   繁体   中英

DEBUG and RELEASE builds in Java (Eclipse)?

New to Java and Eclipse (but experienced with Visual Studio and Delphi). Using Eclipse Mars (4.5) and cannot find how to set the build configuration (DEBUG or RELEASE). Couple of related questions:

  • Are DEBUG/RELEASE supported in Java?
  • How do you switch between the two configurations?
  • Can you detect the configurations at build time and run conditional code like this (using Delphi as an example): {$IFDEF DBG} CallDebugFunction(); {$ELSE} CallReleaseFunction(); {$ENDIF}; {$IFDEF DBG} CallDebugFunction(); {$ELSE} CallReleaseFunction(); {$ENDIF};

DEBUG/RELEASE are not exactly supported in java. But there are a few facts that are useful to remember, and a few other ways of accomplishing parts of the same thing.

The creators of java decided that there is great merit in having every single compilation unit producing the exact same bytecode regardless of external factors, so Java does not have a pre-processor.

The closest thing that java has to the kind of DEBUG/RELEASE that you are familiar with is the assert keyword. You can control whether assertions will be evaluated by supplying an -assertionsenabled ( -ea for short) parameter to the VM. Read up on it, and also read up on how to pass parameters to the VM.

Note that VM parameters are runtime parameters, they have nothing to do with the compiler, which means that assertions will always be emitted by the compiler into the bytecode, and if you do not supply -ea , then the runtime will refrain from evaluating them. So, at the very least there will still always be a hidden if( assertionsEnabled ) { ... } statement to execute for every assertion.

Another thing worth remembering is that public static final variables are treated as compile-time constants, and the compiler may avoid emitting any bytecode for source code controlled by an if( false ) clause. However, the source code will always be compiled, so it has to be correct, despite the fact that no bytecode will be generated.

So, you can have a global variable defined as public static final boolean DEBUG = true to control all your debugging code, but you will have to manually change it in the source code and rebuild your project in order to produce a release build; java specifically refrains from providing any other way of accomplishing this.

Also, note that if( false ) (and by extension if( DEBUG ) ) will produce a warning about the condition being always true or always false, so I don't like using it.

The philosophy of java is that we generally do not care about performance to such a paranoid degree as to want to have total control over tiny little performance differences between DEBUG and RELEASE. Generally, the assert keyword is all that's needed, and actually (to my dismay) most java people do not even use assert due to various (lame, IMHO) reasons.

As for emitting debugging information, the vast majority of debugging info is generated anyway, because it has to be available at runtime through reflection. There is one tiny thing that I am aware of which you can control: the -parameters compiler option, but it is really insignificant, and it is possible that future versions of the compiler will deprecate the option and include the functionality that it controls as standard behavior.

This also means that java code can be reverse-engineered much more easily than C++ code, and for this reason there exist java obfuscators which pass the code through an identifier-mangling phase before sending it to the java compiler, so as to reduce the amount of useful information in the bytecode files.

You might be glad to know that this is all not too bad due to JITting: the bytecode gets compiled into machine code by the VM, and many optimizations are carried out at that stage, so you benefit from them always, not just on RELEASE.

As for detecting whether assertions are enabled, you can use the following code:

static boolean areAssertionsEnabled()
{
    //noinspection UnusedAssignment
    boolean b = false;
    //noinspection ConstantConditions,AssertWithSideEffects
    assert b = true;
    //noinspection ConstantConditions
    return b;
}

The noinspection thingies are for suppressing warnings in IntelliJ IDEA, a java IDE which is far superior to Eclipse. If you insist on using Eclipse you will have to find the equivalent warning suppression mechanisms for it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM