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};
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.
Related
I'm currently working on optimizing a particular method, which is unfortunately inlined by the JVM, which prevents it from being properly vectorized. I've noticed that there is an annotation to forbid inlining, namely jdk.internal.vm.annotation.DontInline . However, it cannot be accessed from the default module.
Is there a clean way of gaining access to this annotation or to prevent the inlining of the offending method some other way?
DontInline, ForceInline, etc. are JDK internal annotations, they cannot be applied to user code. Even if you somehow manage to open these annotations, HotSpot JVM has an explicit check to disallow them for non-privileged classes.
The reasons are understandable. These annotations are the implementation detail of the particular JVM version; JDK developers are free to add/remove/change meaning of such annotations without notice, even in a minor JDK update.
Using #DontInline to force vectorization does not seem a good approach anyway. In general, inlining should not prevent from other optimizations. If you encounter such problem, it's better to report an issue on hotspot-compiler-dev mailing list.
Now the good news.
Since JDK 9, there is a public supported API to manually tune JIT compiler. This is JEP 165: Compiler Control.
The idea is to provide compiler directives in a separate JSON file, and start the JVM with -XX:CompilerDirectivesFile=<file> option. If your application is sensitive to certain compiler decisions, you may provide the directives file along with the application.
{
match: "*::*",
inline: "-org/package/MyClass::hotMethod"
}
It is even possible to apply compiler directives programmatically in runtime using DiagnosticCommand API:
ManagementFactory.getPlatformMBeanServer().invoke(
new ObjectName("com.sun.management:type=DiagnosticCommand"),
"compilerDirectivesAdd",
new Object[]{new String[]{"compiler.json"}},
new String[]{"[Ljava.lang.String;"}
);
By the way, there is Vectorize: true option among the directives list, which may probably help in vectorizing the particular method.
The legacy project I am working on includes some external library in a form of set of binary jar files. We decided that for analysis and potential patching, we want to receive sources of this library, use them to build new binaries and after detailed and long enough regression testing switch to these binaries.
Assume that we have already retrieved and built the sources (I am actually in planning phase). Before real testing, I would like to perform some "compatibility checks" to exclude possibility that the sources represent something dramatically different from what is in the "old" binaries.
Using the javap tool I was able to extract the version of JDK used for compilation (at least I believe it is the version of JDK). It says, the binaries were built using major version 46 and minor 0. According to this article it maps to JDK 1.2.
Assume that the same JDK would be used for sources compilation.
The question is:
Is there a reliable and possibly effective method of verification if both of these binaries are built from the same sources? I would like to know if all method signatures and class definitions are identical and if most or maybe all of method implementations are identical/similar.
The library is pretty big, so I think that detailed analysis of decompiled binaries may be not an option.
I suggest a multi-stage process:
Apply the previously suggested Jardiff or similar to see if there are any API differences. If possible, pick a tool that has an option for reporting private methods etc. In practice, any substantial implementation change in Java is likely to change some methods and classes, even if the public API is unchanged.
If you have an API match, compile a few randomly selected files with the indicated compiler, decompile the result and the original class files, and compare the results. If they match, apply the same process to larger and larger bodies of code until you either find a mismatch, or have checked everything.
Diffs of decompiled code are more likely to give you clues about the nature of the differences, and are easier to filter for non-significant differences, than the actual class files.
If you get a mismatch, analyze it. It may be due to something you do not care about. If so, try to construct a script that will delete that form of difference and resume the compile-and-compare process. If you get widespread mismatches, experiment with compiler parameters such as optimization. If adjustments to the compiler parameters eliminate the differences, continue with the bulk comparison. The objective in this phase is to find a combination of compiler parameters and decompiled code filters that produce a match on the sample files, and apply them to bulk comparison of the library.
If you cannot get a reasonably close match in the decompiled code, you probably do not have the right source code. Even so, if you have an API match it may be worth building your system and running your tests using the result of the compilation. If your tests run at least as well with the version you built from source, continue work using it.
There are a variety of JAR comparison tools out there. One that used to be pretty good is Jardiff. I haven't used it in awhile but I'm sure it's still available. There are also some commercial offerings in the same space that could fit your needs.
Jardiff that Perception mentioned is a good start, however there is no way to do it 100% percent sure theoretically. This is because the same source can be compiled with different compilers and different compiler configurations and optimization levels. So there is no way to compare binary code (bytecode) beyond class and method signatures.
What do you mean by "similar implementation" of a method? Let's suppose that a clever compiler drops an else case because it figures out that the condition may not be true ever. Are the two similar? Yes and no.. :-)
The best way to go IMHO is setting up very good regression test cases that check every key feature of your libraries. This might be a horror, but on long term might be cheaper than hunting for bugs. It all depends on your future plans in this project. Not a trivial easy decision.
For method signatures, use a tool like jardiff.
For similarity of implementation, you have to fall back to a wild guess. Comparing the bytecode on opcode-level may be compiler-dependent and lead to a large number of false negatives. If this is the case, you could fall back to compare the methods of a class using the LineNumberTable.
It gives you a list of line numbers for each method (as long as the class file has been compiled with the debug flag, which is often missing in very old or commercial libraries).
If two class files are compiled from the same source code, then at least the line numbers of each method should match exactly.
You can use a library such as Apache BCEL to retrieve the LineNumberTable:
// import org.apache.bcel.classfile.ClassParser;
JavaClass fooClazz = new ClassParser( "Foo.class" ).parse();
for( Method m : fooClazz.getMethods() )
{
LineNumberTable lnt = m.getLineNumberTable();
LineNumber[] tab = lnt.getLineNumberTable();
for( LineNumber ln : tab )
{
System.out.println( ln.getLineNumber() );
}
}
I need to diagnose all invoked methods in a class(either declared in the class or not) using it's source code. Means that give the class source code to a method as an input and get the invoked method by the class as the output. In fact I need a class/method which operates same as java lexical analyzer .
Is there any method to diagnose all invoked methods ?
of course I tried to use Runtime.traceMethodCalls(); to solve the problem but there was no output. I've read I need to run java debug with java -g but unfortunately when I try to run java -g it makes error. Now what should I do ? Is there any approach ?
1) In the general case, no. Reflection will always allow the code to make method calls that you won't be able to analyze without actually running the code.
2) Tracing the method calls won't give you the full picture either, since a method is not in any way guaranteed (or even likely) to make all the calls it can every time you call it.
Your best bet is some kind of "best effort" code analysis. You may want to try enlisting the compiler's help with that. For example, compile the code and analyze the generated class file for all emitted external symbols. It won't guarantee catching every call (see #1), but it will get you close in most cases.
You can utilize one of the open source static analyzers for Java as a starting point. Checkstyle allows you to build your own modules. Soot has a pretty flexible API and a good example of call analysis. FindBugs might also allow you too write a custom module. AFAIK all three are embeddable in the form of a JAR, so you can incorporate whatever you come up with into your own custom program.
From your question it is hard to determine what is exactly problem you're trying to solve.
But in case:
If you want to analyze source code, to see which parts of it are redundant and may be removed, then you could use some IDE (Eclipse, IntelliJ IDEA Community Edition etc.) In IDE's you have features to search for usages of method and also you have functionality to analyze code and highlight unused methods as warnings/errors.
If you want to see where during runtime some method is called, then you could use profiling tool to collect information on those method invocations. Depending on tool you could see also from where those methods were called. But bare in mind, that when you execute program, then it is not guaranteed that your interesting method is called from every possible place.
if you are developing an automated tool for displaying calling graphs of methods. Then you need to parse source and start working with code entities. One way would be to implement your own compiler and go on from there. But easier way would be to reuse opensourced parser/compiler/analyzer and build your tool around it.
I've used IntelliJ IDEA CE that has such functionalitys and may be downloaded with source http://www.jetbrains.org/display/IJOS/Home
Also there is well known product Eclipse that has its sources available.
Both of these products have enormous code base, so isolating interesting part would be difficult. But it would still be easier than writing your own java compiler and werifying that it works for every corner case.
For analyzing the bytecode as mentioned above you could take a look at JBoss Bytecode. It is more for testing but may also be helpful for analyzing code.
sven.malvik.de
You may plug into the compiler.
Have a look the source of Project Lombok for instance.
There is no general mechanism, so they have one mechanism for javac and one for eclipse's compiler.
http://projectlombok.org/
I am running into the issue where Rhino throws the "Encountered code generation error while compiling script: generated bytecode for method exceeds 64K limit" exception when running Rhino via the javax.script.ScriptEngine API. The accepted solution appears to be to invoke setOptimizationLevel(-1) on the sun.org.mozilla.javascript.Context.
Unfortunately, I cannot seem to access the Context that is created by the ContextFactory. I have tried adding a ContextFactory.Listener to ContextFactory.getGlobal() that would modify the Context after creation, but my listener never seems to get called. I also took a look at the RhinoScriptEngine source from Java 6 to see whether there was a property that I could set that the ContextFactory would read from in order to determine the value of the optimization level.
As far as I can tell, in Java 7, RhinoScriptEngine sets the optimization level to -1 by default and makes it possible to set the optimization level via the rhino.opt.level property. Compare the makeContext() method in the Java 7 version with the makeContext() method in the Java 6 version to see what I mean.
As far as I can tell, I believe that my best option is to run Rhino directly, as shown in this example of using Rhino to run the CoffeeScript compiler. Though as you can see, the code is a lot messier, so I would prefer to use the javax.script.ScriptEngine API, if possible, while continuing to support Java 6. Are there any other options?
No, according to the documentation: http://docs.oracle.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html#jsengine
Where it says:
A few components have been excluded due to footprint and security reasons:
JavaScript-to-bytecode compilation (also called "optimizer"). This
feature depends on a class generation library. The removal of this
feature means that JavaScript will always be interpreted. The
removal of this feature does not affect script execution because the
optimizer is transparent.
The optimizer class has been excluded for bundling it with JDK6 therefore optimization level cannot be set for java 6.
I'm running with 6 and it also appears to be set to -1 by default. Or rather, unless sun.org.mozilla.javascript.internal.optimizer.Codegen is on the classpath, it's set to -1.
How can I compile java code from an arbitrary string (in memory) in Java 5 and Java 6, load it and run a specific method on it (predefined)?
Before you flame this, I looked over existing implementations:
Most rely on Java 6 Compiler API.
Those that don't, rely on tricks.
Yes, I checked out commons-jci. Either I'm too dense to understand how it works, or it just doesn't.
I could not find how to feed the compiler my current class path (which is quite huge).
On the implementation that worked (in Java 6), I could not find how to correctly load inner classes (or inner anonymous classes).
I'd quite like it if the entire thing was in-memory, as the thing runs on multiple environments.
I'm sure this has been solved before, but I can't find anything that looks even half-production quality on google (except jci, which, as I've said before, I haven't managed to use).
Edit:
I looked over JavaAssist - I need inner classes, Java 5.0 language level support and compiling with the entire classpath. Also, I'd like to create new classes on the fly. I
might be mistaken, but I couldn't find how to do this with JavaAssit.
I'm willing to use a file-system based solution (calling javac) but I don't know how to divine the classpath, nor how to later load the files (which are not in my classpath) with a special classloader that can be recycled for multiple invocations. While I do know how to research it, I'd prefer a ready solution.
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.
I don't want to mark the answer as accepted yet since I do hope for a better solution to come up.
Edit3: Accepted the beanshell suggestion - it really works wonderfully.
JCI looks fine. This code snippet should be your base:
JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");
MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());
MemoryResourceStore mrs = new MemoryResourceStore();
CompilationResult result = compiler.compile(sources, mrr, mrs);
// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir
Any reason this should not work?
Edit: added a MemoryResourceStore to send the compiled class output to memory, like requested.
Also, setting javac settings, like classpath in your case, can be done via setCustomArguments(String[] pCustomArguments) in JavacJavaCompilerSettings class.
You might want to check out Janino as well.
From their website:
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.
http://www.janino.net/
Im currently using it in a pretty large mission critical project and it works just fine
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)
Beanshell should run any 100% java code IIRC, and I believe Groovy can run most java code--possibly all.
Javassist might interest you
Run inside a web container like Tomcat and first generate a JSP page, and then invoke it.
This also allow you to get rid of the old class definitions by simply overwriting the JSP page instead of having your classloader slowly run full.
Is the "in-memory" requirement due to speed or due to not changing the code base?
ECJ Eclipse Java Compiler
Eclipse provides and uses its own compiler that is not javac
The Eclipse compiler is used inside the IDE (Eclipse)
The Eclipse compiler can also be used as a pure batch compiler
outside of Eclipse
Compile a source file
$ java -jar ecj-3.5.2.jar HelloWorld.java