can JIT optimize such unnecessary call? - java

I have question about JIT optimization.
I compiled a simple piece of code:
class btest
{
static final boolean flag=false;
public final void foo(int x)
{
if(flag) {a=x; b=x*2; c=x*3;}
}
public void bar(int y) {foo(y);}
int a,b,c;
};
flag is set to false so foo() is perfectly compiled to empty code - just returns.
But bar() still calls it.
Is it possible that JIT will eliminate this call?
Does it matter if flag belongs to external class?
regards

It can eliminate it and inline it in code.
Note: It can also do this for non-volatile non-final variables where it thinks the thread doesn't change the value. A common mistake is something like
boolean running = true;
public void run() {
while(running) {
// do something
}
}
public void stop() {
running = false;
}
A common misconception is that the thread might keep running for an while but stop at some unknown point, when actually the JIT might inline running and never stop.

The JIT compiler would most likely be able to eliminate this.
But actually, I think that the if statement is likely to be optimized away before then. The reason is in JLS 14.21 starting at the point where is says this:
"However, in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ."
If goes on to say that that the compiler (that is the bytecode compiler!) may generate different code in your example depending on the known value of the condition at compile time.
Note that this special treatment only applies to if statements, and only if the condition is a constant expression. (That term has a very specific meaning - see JLS 15.28) If you tried the same "trick" with a while loop for example, you would get a compilation error complaining about unreachable code.
(This "conditional compilation" special treatment goes back to the early days of Java, and is part of the rationale for Gosling et al's decision to not include a preprocessor in the Java language.)

Related

Why Java couldn't figure out some obvious illegal casts when type parameters are involved?

Consider the following example:
public class Example {
public static <T> void f(T obj) {
Integer i = (Integer) obj; // runtime error
}
public static void main(String[] args) {
f("hello");
}
}
Is there any reason why Java cannot figure out that cast in line 3 is illegal in compile time? Surely, because of the type erasure, the signature of the function in runtime will be f(Object obj), but it seems to me that in the compile-time it's enough information to catch the error.
Compare this with the case:
List<String> ls = new ArrayList<>();
ls.add(42); // compile-time error
ls.add("foo");
Integer i = ls.get(0); // compile-time error
where a type parameter is involved but the error succesfully detected in the compile-time.
If the answer is "the compiler is just not smart enough", then is there any reason (for backward compatibility?) why it can't be made smarter?
Explanation
Java, based on its current rule set (see the JLS) has to treat the method content and its call-site separately.
Method content
The cast
(Integer) obj
has to be allowed at compile-time since T could be an Integer. After all, a call like
f(4)
should succeed and be allowed.
Java is not allowed to take in the call-site of the method into consideration. Also, this would imply that Java would have to scan all call-sites but this is impossible since that would also include possible future call-sites that have not been written yet or are included later on, in case you are writing a library.
Call-site
The call-site also has to be legal since Java is not allowed to take the method-content into consideration.
The signature demands T (extends Object) and String fullfills that. So it is allowed to be called like that.
If Java would also check the content, imagine you would hide the cast 3 levels depper in some other method calls. Then Java not only has to check fs code but also the code of those methods and possibly all their if statements to check if the line with the bad cast is even reached.
It is NP-hard to prove that with 100% certanity at compile-time, hence it is also not part of the rule set.
Why?
While we saw that such situations are not always easy to detect and that actually proving it for all possible situations might even be impossible (NP-hard), Java designers could certainly have added some weaker rules that cover the dangerous situations partially.
Also, there are actually some similar situations in which Java will help you out with weaker rules. For example a cast like
House a = new House();
Dog b = (Dog) a;
is forbidden because Java can prove easily that the types are completely unrelated. But as soon as the setup becomes more complex, with types coming from other methods, generics, Java can not easily check it anymore.
All in all, you will have to ask a Java Language Designer for the precise reasons in the decision making. It is what it is.
Static code analysis
What you have here is typically the job of a static code analyzer (like most IDEs already include). They will actually scan through your code, all usages and so on and try to figure out if your current code flow has possible issues.
It is important to note that this also includes a lot of false-positives, as we just learned that not all of such usages might actually be wrong, some dangerous setups might be intended.
Appendix: Comments
Based on the discussion in the comments, let me stress out the fact that your particular example is indeed simple to prove to be wrong. So the call-site could easily be forbidden in this particular case (any static code analyzer will happilly throw a warning at you for this code).
However, we can do very simple modifications to the code already that demonstrates why it is so difficult to actually prove errors when connecting the call-site with the content of the method.
So the tldr is that almost all real code situations require much more efforts for a tool to prove with 100% that the call is incorrect. Also, it is much more difficult to program this and it can not always be ensured that there are no false-positives. Which is why such stuff is typically not done by a compiler but rather by static code analyzers.
The two common examples for this are method nesting and code branching.
Nesting
Imagine you hide the cast (Integer) obj a level depper, in another method:
public static void main(String[] args) {
f("hello");
}
public static <T> void f(T obj) {
g(obj);
}
public static <T> void g(T obj) {
Integer i = (Integer) obj;
}
In order to prove this, Java would now have to connect the call-site from main to the content in f, to the call-site in g. If you add more levels of nesting this quickly gets out of control and needs a recursive deep analysis before anything can be proven.
Branching
Another very common but difficult situation for the compiler is if you hide the bad cast in a branched code flow:
public static void main(String[] args) {
f("hello");
}
public static <T> void f(T obj) {
if (isMonday()) {
Integer a = (Integer) obj;
} else {
String b = (String) obj;
}
}
Now, Java would need knowledge about what isMonday() returns at compile-time, which is simply impossible.
But if Java flags this, it would be bad. Because, what if we ensure externally that we only launch the program mondays? It should work then.

can moderm JVMs optimize different instances of the same class differently?

say I have 2 instances of the same class, but they behave differently (follow different code paths) based on a final boolean field set at construction time. so something like:
public class Foo {
private final boolean flag;
public Foo(boolean flagValue) {
this.flag = flagValue;
}
public void f() {
if (flag) {
doSomething();
} else {
doSomethingElse();
}
}
}
2 instances of Foo with different values for flag could in theory be backed by 2 different assemblies, thereby eliminating the cost of the if (sorry for the contrived example, its the simplest one I could come up with).
so my question is - do any JVMs actually do this? or is a single class always backed by a single assembly?
Yes, JVMs do this form of optimization. In your case, this would be a result of inlining and adaptive optimization for being a value to always be true. Consider the following code:
Foo foo = new Foo(true);
foo.f();
It is trivial to prove for HotSpot that Foo is always an actual instance of Foo at the call site of f what allows the VM to simply copy-paste the code of the method, thus eliminating the virtual dispatch. After inlining, the example is reduced to:
Foo foo = new Foo(true);
if (foo.flag) {
doSomething();
} else {
doSomethingElse();
}
This again, allows to reduce the code to:
Foo foo = new Foo(true);
foo.doSomething();
If the optimization can be applied does therefore depend on the monomorphism of the call site of foo and the stability of flag at this call site. (The VM profiles your methods for such patterns.) The less the VM is able to predict the outcome of your program, the less optimization is applied.
If the example was so trivial as the above code, the JIT would probably also erase the object allocation and simply call doSomething. Also, for the trivial example case where the value of the field can be proven to be true trivially, the VM does not even need to optimize adaptively but simply applies the above optimization. There is a great tool named JITWatch that allows you to look into how your code gets optimized.
The following applies to hotspot, other JVMs may apply different optimizations.
If those instances are in turned assigned to static final fields and then referred to by other code and the VM is started with -XX:+TrustFinalNonStaticFields then those instances can participate in constant folding and inlining CONSTANT.f() can result in different branches being eliminated.
Another approach available to privileged code is creating anonymous classes instead of instances via sun.misc.Unsafe.defineAnonymousClass(Class<?>, byte[], Object[]) and patching a class constant for each class, but ultimately that also has to be referenced through a class constant to have any effect on optimizations.

Java: What is considered more readable, "this" or no "this"

You don't really need to write the "this" keyword in Java. But is it better to do so anyway? Does it make sense to homogenise your style, i.e. if you use "this" once, you use it every time it's implied? Or is there a place where you would always use it and others where you never use it?
The general consensus is that you should use this only when it is necessary and not at any other time.
private String param;
public Construct(String param) {
// Usually the only place you need to use this.
this.param = param;
}
// A less common use of this
public Function() {
synchronized(this) {
// Some synchronized stuff.
}
}
As a rule I tend not to use it - if you can reduce redundant code then all the better.
There are however three places that I can think of where the this keyword cant be avoided:
Constructors (delegating to another constructor in the same class)
public MyClass() {
this("Default Parameter");
Synchronizing on the current object
synchronized(this) {
Passing the current object to another class
public void methodOne() {
anotherClass.doSomething(this);
You sometimes need it in constructors where the field name is the same as the parameter, but this isnt really mandatory as you could simply rename the paramter:
public MyClass(String data) {
this.data = data
Other than these I cant think of too many other scenarios where I'd use the this keyword. I have seen it overused (on every method and field reference) and this can make the code very hard to read.
Use it only when you have to, or when you believe that it enhances code readability.
As a general rule you should avoid redundant syntax wherever it may arise. You will read lots of opinion to the contrary, mostly referring to a thoroughly mythical programmer who doesn't know about member variables, doesn't know what parentheses are for, and doesn't remember the rules of operator precedence he was taught in third grade. I've never met him in 40 years. That isn't enough to justify disfiguring your code for him on the assumption that he will (a) not understand it and (b) therefore break it. I've never seen that happen at all.
What I have seen is code produced by such a person. That's not a reason to dumb down your own code for him. The occasions on which someone has actually gone as far as to incorrectly rewrite a piece of code of mine are exactly two: once in 1979, where someone refactored a grammar to remove the operator precedence, which was dumb, and he shouldn't have done it, and another time in about 1992, but in both cases there is no way I could have written the grammar or the code that would have prevented it.
There are some places in code, where you couldn't skip this keyword, e.g. setters:
public void setValue(String value) {
this.value = value;
}
But if its possible it's better to skip:
public String getValue() {
return value;
}

Conditional JIT-compilation

In Java we can do conditional compilation like so
private static final boolean DO_CHECK = false;
...
if (DO_CHECK) {
// code here
}
The compiler will see that DO_CHECK is always false and remove the entire if-statement. However, sometimes, especially in library code, we can't use conditional compilation, but I'm wondering, can we use conditional JIT-compilation?
private final boolean doCheck;
public LibraryClass(boolean d) {
doCheck = d;
}
public void oftenCalledMethod() {
if (doCheck) {
...
}
}
If we construct LibraryClass with doCheck = false, will the JIT-compiler (in Hotspot) remove the if-statement as well?
Update: I just realised that JIT-compilation is most probably not done on instance level, so I think this wouldn't work, but maybe there's a static way?
JIT stands for "just in time". That means stuff is compiled just before the VM thinks it needs it. So depending on the level of atomicity of checking you might find the code that never gets run never gets JIT compiled anyway.

Equivalent code for instance method synchronization in Java

While discussing a Java synchronization question, someone made a comment that the following snippets are not equivalent (and may compile to different bytecodes):
public synchronized void someMethod() {
//stuff
}
and
public void someMethod() {
synchronized (this) {
//stuff
}
}
Are they equivalent?
They are equivalent in function, though the compilers I tested (Java 1.6.0_07 and Eclipse 3.4) generate different bytecode. The first generates:
// access flags 33
public synchronized someMethod()V
RETURN
The second generates:
// access flags 1
public someMethod()V
ALOAD 0
DUP
MONITORENTER
MONITOREXIT
RETURN
(Thanks to ASM for the bytecode printing).
So the difference between them persists to the bytecode level, and it's up to the JVM to make their behavior the same. However, they do have the same functional effect - see the example in the Java Language Specification.
It should be noted, that if the method is overridden in a subclass, that it is not necessarily synchronized - so there is no difference in that respect either.
I also ran a test to block a thread trying access the monitor in each case to compare what their stack traces would look like in a thread dump, and they both contained the method in question, so there is no difference there either.
I made the original comment that the statements are identical.
In both cases, the first thing that happens is that the calling thread will try to acquire the current object's (meaning, this') monitor.
I don't know about different bytecode, I'll be happy to hear the difference. But in practice, they are 100% identical.
EDIT: i'm going to clarify this as some people here got it wrong. Consider:
public class A {
public synchronized void doStuff()
{
// do stuff
}
}
public class B extends A {
public void doStuff()
{
// do stuff
// THIS IS OVERRIDE!
}
}
In this case doStuff() in class B still overrides doStuff() in class A even though it is not synchronized.
Synchronized keyword is never part of the contract! Not for subclasses, not for interfaces, not for abstract classes.
I made the original comment. My comment was that they are logically equivalent, but compile to different bytecode.
I didn't add anything else to justify it at the time because there's not much to justify really-- they just do compile to different bytecode. If you declare a method as synchronized, then that synchronization is part of the method's definition. A synchronized block within a method isn't part of the method's definition, but instead involves separate bytecodes to acquire and release the monitor, as one of the posters above has illustrated. Strictly speaking, they're slightly different things, though to the overall logic of your program, they're equivalent.
When does this matter? Well, on most modern desktop VMs, hardly ever. But for example:
a VM could in principle make optimisations in one case but not the other
there are some JIT compiler optimisations where the number of bytecodes in the method is taken as a criterion for what optimisations to make
a VM without a JIT compiler (admittedly few nowadays, but maybe on an older mobile device?) will have more bytecodes to process on each call
Yes. Using the synchronized keyword on an instance method uses 'this' as a monitor ,also using it on a class method (static method) uses the class' Class object (Foo.class).
This way you can synchronize entire methods, and in the same time, synchronize it with a code snippet in another method using the synchronized-block style.
I can't see any functional difference - both synchronize their entire method bodies on (this). How did the person who commented that these are different justify their statement?
They are not quite equivalent in function. Other code could use reflection to see if your method has the synchronized modifier, but there is no way to tell if a method contains a synchronized block without reading its bytecode.
The ability to determine if a method is synchronized occasionally comes in handy. Personally, I've used that flag to avoid redundant locking when doing synchronization in aspect-oriented programming.
MyObject myObjectA;
MyObject myObjectB;
public void someMethod() {
synchronized (this) {
//stuff
}
}
public void someMethodA() {
synchronized (myObjectA) {
//stuff
}
}
public void someMethodB() {
synchronized (myObjectB) {
//stuff
}
}
In this case:
someMethod blocks entire class
someMethodA blocks myObjectA only
someMethodB blocks myObjectB only
someMethodA and someMethodB can be invoked at the same time

Categories