Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a zero-time, startup (no recompilation) switchable condition flag in Java?

I'm looking for a way to provide the fastest (I mean zero-time - compilation/classloading/JIT time resolved) possible On/Off flag for if condition. Of course this condition will be changed only once per application run - at startup.

I know that "compile-time constant if conditions" can be conditionaly compiled and whole condition can be removed from code. But what is the fastest (and possibly simple) alternative without need to recompile sources?

Can I move condition to separate .jar with single class & method with condition, where I produce two versions of that .jar and will swtich those versions in classpath on application startup? Will JIT remove call to method in separate .jar if it discovers, that method is empty?

Can I do it by providing two classes in classpath implementing "ClassWithMyCondition", where one of those class will have a real implementation and second will have just empty method and instantiate one of it by Class.forName and .newInstance()?Will JIT remove call to empty method from my primary very loop-nested method?

What can be simplest byte-code manipulation solution to this problem?

like image 363
Piotr Müller Avatar asked Oct 24 '13 19:10

Piotr Müller


4 Answers

A standard way to do this sort of logic is to create an interface for the functionality you want, and then to create two (or more) implementations for that functionality. Only one of the implementations will be loaded in your runtime, and that implementation can make the assumptions it needs to in order to avoid the if condition entirely.

This has the advantage that each implementation is mutually exclusive, and things like the JIT compiler can ignore all the useless code for this particular run.

like image 111
rolfl Avatar answered Nov 17 '22 12:11

rolfl


The simplest solution works here. Don't overcomplicate things for yourself.

Just put a final static boolean that isn't a compile-time constant (as defined in the JLS) somewhere and reference it wherever you want the "conditional" compilation. The JVM will evaluate it the first time it sees it, and by the time the code gets JIT'ed, the JVM will know that the value won't change and can then remove the check and, if the value is false, the block.

Some sources: Oracle has a wiki page on performance techniques which says to use constants when possible (note that in this context, the compiler is the JVM/JIT, and therefore a final field counts as a constant even if it isn't a compile-time constant by JLS standards). That page links to an index of performance tactics the JIT takes, which mentions techniques such as constant folding and flow-sensitive rewrites, including dead code removal.

like image 20
yshavit Avatar answered Nov 17 '22 11:11

yshavit


You can pass custom values in the command line, and then check for that value once. So in your code, have something like this:

final static boolean customProp = "true".equalsIgnoreCase(System.getProperty("customProp"));

Depending on your command line parameters, the static final value will change. This will set the value to true:

java -DcustomProp="true" -jar app.jar

While this will set the value to false:

java -jar app.jar

This gives you the benefits of a static final boolean, but allows the value to be altered without recompiling.


[Edit]

As indicated in the comments, this approach does not allow for optimizations at compile time. The value of the static final boolean is set on classload, and is unchanged from there. "Normal" execution of the bytecode will likely need to evaluate every if (customProp). However, JIT happens at runtime, compiling bytecode down to native code. At this point, since the bytecode has the runtime value, more aggressive optimizations like inlining or excluding code are possible. Note that you cannot predict exactly if or when the JIT will kick in, though.

like image 20
Eric Grunzke Avatar answered Nov 17 '22 11:11

Eric Grunzke


you should load the value from a properties file so that you can avoid having to recompile each time it cahnges. Simply update the text file and on next program run, it uses the new value. Here's an example I wrote a long time ago:

https://github.com/SnakeDoc/JUtils/blob/master/src/net/snakedoc/jutils/Config.java

like image 1
SnakeDoc Avatar answered Nov 17 '22 13:11

SnakeDoc