Edit2:For now, I'm content with BeanShell "evaluate". Apparently it does everything I need it to (get a string, evaluate it in the context of the 'current' classpath. It does miss some of Java 5 features, but it can use enums (not define) and compiled 'generic' (erased) classes, so it should be enough for what I want.
Janino is a compiler that reads a JavaTM expression, block, class body, source file or a set of source files, and generates JavaTM bytecode that is loaded and executed directly. Janino is not intended to be a development tool, but an embedded compiler for run-time compilation purposes, e.g. expression evaluators or "server pages" engines like JSP.
If you're not completely tied to compiling, solutions like Beanshell, groovy and the other scripting languages are easily embedded (in-fact, java has built-in support for plugging in a scripting language so your code doesn't even know what language the script is written in)
The suggestions about using custom class loaders and dynamically commented code are a bit incredulous when it comes to maintenance and the preservation of the sanity of whichever poor soul picks up the project after you shuffle to pastures new.
The solution is easy. Pull the affected classes out into two separate, independent projects - make sure the package names are the same, and just compile into jars that you can then consume in your main project. If you keep the package names the same, and the method signatures the same, no problems - just drop whichever version of the jar you need into your deployment script. I would assume you run separate build scripts or have separate targets in the same script - ant and maven can both easily handle conditionally grabbing files and copying them.
Assuming that the classes have similar functionality with 1.5 vs. 6.0 differences in implementation you could merge them into one class. Then, without editing the source to comment/uncomment, you can rely on the optimization that the compiler always do. If an if expression is always false, the code in the if statement will not be included in the compilation.
Then when you want to compile the other version you just have to change that one variable and recompile. It might make the java file larger but it will consolidate your code and eliminate any code duplication that you have. Your editor may complain about unreachable code or whatever but the compiler should blissfully ignore it.
I think the best approach here is probably to use build scripts. You can have all your code in one location, and by choosing which files to include, and which not to include, you can choose what version of your code to compile. Note that this may not help if you need finer-grained control than per file.
Keep one "master" source root that builds under JDK 5. Add a second parallel source root that has to build under JDK 6 or higher. (There should be no overlap, i.e. no classes present in both.) Use an interface to define the entry point between the two, and a tiny bit of reflection.
You could configure these as separate projects in an IDE using different JDKs, etc. The point is that the main root can be compiled independently and it is very clear what you can use in which root, whereas if you try to compile different parts of a single root separately it is too easy to accidentally "leak" usage of JDK 6 into the wrong files.
Rather than using Class.forName like this, you can also use some kind of service registration system - java.util.ServiceLoader (if main could use JDK 6 and you wanted optional support for JDK 7!), NetBeans Lookup, Spring, etc. etc.
That said, you should stick with at least having one file version for Java 5 and one for Java 6, and include them via a build or make as appropriate. Sticking it all in one big file and trying to get the compiler for 5 to ignore stuff it doesn't understand isn't a good solution.
This will make all the Java purists cringe (which is fun, heh heh) but i would use the C preprocessor, put #ifdefs in my source. A makefile, rakefile, or whatever controls your build, would have to run cpp to make a temporary files to feed the compiler. I have no idea if ant could be made to do this.
While stackoverflow looks like it'll be the place for all answers, you could wehn no one's looking mosey on over to for Java wisdom. I imagine this question has been dealt with there, prolly a long time ago.
You can get conditional compile, but not very nicely - javac will ignore unreachable code. Thus if you structured your code properly, you can get the compiler to ignore parts of your code. To use this properly, you would also need to pass the correct arguments to javac so it doesn't report unreachable code as errors, and refuse to compile :-)
The public static final solution mentioned above has one additional benefit the author didn't mention--as I understand it, the compiler will recognize it at compile time and compile out any code that is within an if statement that refers to that final variable.
You can use reflection API. put all your 1.5 code in one class and 1.6 api in another. In your ant script create two targets one for 1.5 that won't compile the 1.6 class and one for 1.6 that won't compile the class for 1.5. in your code check your java version and load the appropriate class using reflection that way javac won't complain about missing functions. This is how i can compile my MRJ(Mac Runtime for Java) applications on windows.
According to that article, Java Compiler i.e. javac does not perform any optimization while generating bytecode. Is it really true? If so, then can it be implemented as an intermediate code generator to remove redundancy and generate optimal code?
The point is that the JIT compiler does most of the optimization - and it works best if it has a lot of information, some of which may be lost if javac performed optimization too. If javac performed some sort of loop unrolling, it would be harder for the JIT to do that itself in a general way - and it has more information about which optimizations will actually work, as it knows the target platform.
More importantly, the javac compiler does not perform simple optimizations like loop unrolling, algebraic simplification, strength reduction, and others. To get these benefits and other simple optimizations, the programmer must perform them on the Java source code and not rely on the javac compiler to perform them.
Firstly, doing loop unrolling on Java source code is hardly ever a good idea. The reason javac doesn't do much in the way of optimization is that it's done by the JIT compiler in the JVM, which can make much better decisions that the compiler could, because it can see exactly which code is getting run the most.
However starting J2SE1.3, the HotSpot JVM was shipped with the platform, which introduced dynamic techniques such as just-in-time compilation and adaptive optimization of common execution paths. Hence the -o was ignored by the Java compiler starting this version.
Indicates whether source should be compiled with optimization; defaults to off. Note that this flag is just ignored by Sun's javac starting with JDK 1.3 (since compile-time optimization is unnecessary).
The Server VM contains an advanced adaptive compiler that supports many of the same types of optimizations performed by optimizing C++ compilers, as well as some optimizations that cannot be done by traditional compilers, such as aggressive inlining across virtual method invocations. This is a competitive and performance advantage over static compilers. Adaptive optimization technology is very flexible in its approach, and typically outperforms even advanced static analysis and compilation techniques.
I have studied outputted Java bytecode in the past (using an app called FrontEnd). It basically doesn't do any optimization, except for inlining constants (static finals) and precalculating fixed expressions (like 2*5 and "ab"+"cd"). This is part of why is is so easy to disassemble (using an app called JAD)
A method has 5 quick-access variables. When these variables are called, they're faster than all other variables (probably because of stack maintainance). The parameters of a method are also counted to these 5. So if you have code inside for loop which is executed like a million times, allocate those variables at the start of the method, and have no parameters.
Local variables are also faster than fields, so if you use fields inside inner loops, cache these variables by assigning them to a local variable at the start of the method. Cache the reference not the contents. (like: int[] px = this.pixels;)
As others have noted, the JIT in a mainstream JVM will optimize the code while compiling it. It will probably outperform Proguard, because it has access to more context. But ths may not be the case in more simple VMs. In the Android world it is common practice to use Proguard optimizations when targeting Dalvik (the VM that came with Android before Lollipop).
When you want a computer to perform tasks, you write a program. A program is a sequence of instructions that define tasks for the computer to execute. This lesson explains how to write, compile, and run a simple program written in the Java language (Java program) that tells your computer to print a one-line string of text on the console.
The simple program in this lesson uses a Java API to print a line of text to the console. The console printing capability is provided in the API ready for you to use; you supply the text to be printed.
Java programs are run (or interpreted) by another program called the Java VM. If you are familiar with Visual Basic or another interpreted language, this concept is probably familiar to you. Rather than running directly on the native operating system, the program is interpreted by the Java VM for the native operating system. This means that any computer system with the Java VM installed can run Java programs regardless of the computer system on which the applications were originally developed.
d3342ee215