How does method/field visibility impact on method inlining in Java?
The case I have in mind is something like a public getter for a private field:
private Thing blah;
public Thing getBlah() {
return blah;
}
There are several issues that arise here.
For one, does the Java compiler itself do any inlining? This question seems to be answered variously, with some saying yes and some saying no. I don't know whether that's because it used not to do any inlining but now does, or whether it's just that some people are right and some people are wrong...
Now, if it does do some inlining, am I right in thinking that it can't possibly inline getBlah() calls? They would be an obvious place for inlining to be useful, because the method is very simple, and the overhead of invoking a method is as big as the code for the method itself. But if it got inlined by the compiler, you'd end up with bytecode that accessed a private field directly; and surely the JVM would then complain? (This would apply even if this method were static final.)
Secondly, what about the JIT compiler? As far as I can see, this problem doesn't apply when it comes to inlining at that level. Once it's producing native code, the JVM has already done its checks, and confirmed that I can invoke the method (because it's public); so it can then generate native code that inlines the call, without any visibility issues... yes?
The javac compiler (and any valid java compiler) will not and can not inline getters; think about it: You could extend a class from that class and overwrite the getter. And yes if a compiler would overzealously inline that access it would not pass the verifier (well at least it should not pass the verifier, but they don't verify everything - in java 1.3 you could even make main() private and it would still work... likewise there used to be an -O option in javac that did sometimes screw your code).
The JIT is a whole other beast; it knows (well at least nowadays) at any time if there is an overwite for a method or not. Even if a class is later loaded that overwrites the getter, it can deoptimize already JIT'd methods to refelect alterations on the inhertance tree (thats one of the optimizations AOT compilers lack the information for).
Thus it can safely inline whatever it wants. It also doesn't need to artificially uphold access modfiers, because there is no such thing in the compiled machine code and again it knows what is a vaild code transformatiom (and since getters are so common its also a low hanging fruit for the JIT to optimize).
Edit: To make it absolutely clear, above paragraphs address potentially virtual methods; specifically those that are not private, static or final. Javac could perform inlining in some cases; because it could prove that no override can exist for those. It would be a pointless undertaking in face of the fact that the JIT also does it, and it does a far better job at it.
javac does not inline methods, even as simple as getBlah() and setBlah()
As to HotSpot JVM, JIT compiler does inline all such methods unless it reaches the maximum level of inlining (-XX:MaxInlineLevel)
JIT equally treats public and private methods in terms of inlining. Access modifiers does not generally affect inlining unless some very specific cases.
Whether or not any particular Java compiler -- Oracle's, for instance -- performs any inlining is an implementation detail that you would be better off ignoring. A future generation of your chosen compiler or an alternative compiler might operate differently than the one you happen to be looking at now.
To the extent that a Java compiler did perform inlining, however, it could inline only private methods and constructors. Anything else is a candidate for access from (unknowable) other classes.
A JIT compiler, on the other hand, can do pretty much anything it wants, including inlining public methods. It is responsible for any adjustments that may be needed when new classes are loaded. Beans-style accessor methods are a particularly likely thing for a JIT to optimize, they being such a common pattern.
Related
Well, that title along can't get the idea across but basically what I mean is that given some method m() in a class Base, which is not overridden in some subclass Derived, are the JIT compilers in current JVMs1 capable of "specializing"0 m() anyway when it makes sense, or will derived who inherit and don't override Base.m() share the same compiled code?
This specialization makes sense, where the derived class defines something that makes m() much simpler. For example and for the purposes of discussion, let's say m() calls another member function n() and in the derived class n() is defined such that when n() is inlined into m() the latter is greatly simplified.
To be concrete, consider following the two non-abstract methods in the following class (which are both m()-type methods, while the abstract methods are the corresponding n() methods):
public class Base {
abstract int divisor();
abstract boolean isSomethingEnabled();
int divide(int p) {
return p / divisor();
}
Object doSomething() {
if (isSomethingEnabled()) {
return slowFunction();
} else {
return null;
}
}
Both rely on abstract methods. Lets say you now have a Derived like this:
public class Derived extends Base {
final int divisor() {
return 2;
}
final boolean isSomethingEnabled() {
return false;
}
}
Now the effective behavior of the divide() and doSomething() methods are very simply, the divide is not a full division by an arbitrary number, but a simply halving that can be done with bit-operations. The doSomething() method always returns false. I assume that when the JIT goes to compile divide() or doSomething() if Derived is the only subclass, all is good: there exists (currently) only one possible implementation for the two abstract calls, and CHA will kick in and inline the only possible implementations and all is good.
In the more general case that other derived classes exist, however, it isn't clear to me if the JVM will only compile one2 version of the methods in Base with an invokevirtual call to the abstract methods, or if it is smart enough to say, "Hey, even though Derived doesn't override divisor() I should compile a version specifically for it 'cause it's going to be much simpler".
Of course, even without specialized recompilation aggressive inlining often makes it work out fine anyway (i.e., when you call divide() on a class that is known or even just likely to be a Derived, inlining is likely to give you the good implementation anyway, but, equally, there are plenty of cases where such inlining isn't done.
0 My specializing I don't mean anything specific beyond compiling another version of the function appropriate in some restricted domain, in the same sense that say inlining is a form of specialization to a specific call site, or in the same way that most functions are somewhat specialized to the current context (e.g., loaded classes, assumptions about nullness, etc).
1In particular, when one says "Can the JVM blah, blah?" one is usually talking about Hotspot, and I'm also mostly in Hotspot but also whether any other JVM can do this too.
2OK sure, you might have several version of a function, for on-stack-replacement, for different compiler levels, when deoptimization occurs, etc...
HotSpot JVM has at most one current, entrant version of compiled method. This is obvious from one-to-one relationship between Method and nmethod entities in the source code. However, there can be multiple non-entrant previous versions (e.g. nmethods compiled at lower tier and OSR stubs).
This single compiled version is often optimized for the most common case basing on run-time profiling. For example, when during profiling of Base.doSomething() JIT sees that isSomethingEnabled() is always invoked on Derived instance (even if there are more subclasses), it will optimize the call for the fast case, leaving an uncommon trap for a slow one. After this optimization doSomething() will look like
if (this.getClass() != Derived.class) {
uncommon_trap(); // this causes deoptimization
}
return false;
Profile data is collected separately for each branch and for each call site. This makes possible to optimize (specialize) a part of a method for one receiver, and the other part for a different receiver.
If two different receivers were detected during profiling, JIT can inline both callees guarded by a type check.
A virtual call with more than two receivers will be compiled using vtable lookup.
To see the method profile data use -XX:+PrintMethodData option available in debug builds of JVM.
No, my understanding is that the JVM would not specialize a method on its own but rather optimize the base class function if it finds during profile optimization that divisor() often resolves to a certain method.
Have you tried to print from diagnostics to see what happens?
Rather than trying to guess what the JIT is doing, you can take a peek
at what’s happening by turning on java command line flags:
-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining (from Java JIT compiler inlining)
According to the OpenJDK Wiki:
Methods are often inlined. This increases the compiler's "horizon" of optimization.
Static, private, final, and/or "special" invocations are easy to inline.
Virtual (and interface) invocations are often demoted to "special" invocations, if the class hierarchy permits it. A dependency is registered in case further class loading spoils things.
Virtual (and interface) invocations with a lopsided type profile are compiled with an optimistic check in favor of the historically common type (or two types).
That is, for the two most frequent receiver types, the derived methods would be inlined into their caller (if small enough, which should be the case here), and unreachable branches pruned.
Also, if the base method is small enough for inlining into its caller, it will be optimized for that caller's two most frequent receiver types.
That is, the Hotspot JVM specializes code if it is small enough for inlining for the two most frequent receiver types of that call site.
The JVM doesn't define nor redefine types. It interprets running implementations of behaviors. It's the compiler, i.e., the source language that deals in types. The JVM is the low level, the "metal" of the Java universe. Types and their instances are instructions to create a series of observable events influenced by inputs. That series of inputs and observable events over time constitute what computer scientists call the "semantics" of a program.
It's up to the JVM to figure out ways to carry out those instructions while preserving the semantics. It will, at times, destroy a class structure entirely, in effect. Conceptually a class instance lives in heap memory with labeled attributes. For some period of time, until the semantics prohibit it because of some state change, the JVM might keep two active values in registers, not even in RAM, and ignore the whole rest of the defined class. Is that "specializing" the method?
No, it is not. There is no new definition, no new set of Java-level instructions, no ephemeral type in the JVM. There's just a temporary, compiled and optimized way in the moment to fulfill the instructions. When the optimization no longer works, or matters as much, the JVM even reverts to interpreting bytecode. And bytecode won't contain any new types, either. It's an assembly language, and redefining what the high-level code demands is above its pay grade.
Bottom line, the only types in the program are those mandated in the source code, not the bytecode or JVM. All the semantics come from the source.
My question is pretty straightforward:
Q: What is the chance that a getter / setter method will get inlined by the compiler in Java?(Obviously there isn't a definite answer to this, but other information would be appreciated)
Extra: I understand there is always a chance the compiler (Standard and JIT) will decide to make a method inline, and when it comes to getters and setters this is usually what the programmer wants.
Thanks in advance.
The compiler (javac) tend to have negligible impact on optimization,
as optimization happens at run time.
As of the JIT yes,it will probably inline either sooner or later.depending on how heavily the code is used, so a function call overhead may be seen at first, but when the getter/setter has been called sufficiently often then it is inlined.
The compiler may inline when a method is final and the accessed fields are accessible to the caller. Then it's up to the compiler to determine whether the method is "simple" enough for inlining.
In practice, setting or getting a field is generally considered simple enough, so a final accessor for an accessible field will be inlined. Accessors for private fields will be inlined within their declaring class; accessors for protected fields will be inlined throughout the declaring package and any derived classes; &c.
At runtime, the JIT is likely to perform additional inlining based on analysis of running code.
I imagine about zero (at least in the non-JIT case), since these are Java Bean conventions and they always need to be public, so the compiler cannot predict who might call the methods. You might change the implementation of one of these which would break an inlined caller. There is nothing to require that they need to be implemented only to set a field.
Has Java like other languages a directive to inline a method at compile time or at JIT time?
We have many methods that call only the super method. This make it clear that it was not forget to override the method.
For example you have override the equals methods but was use the same hashcode like super implementation. This make clear for a later developer that the hashcode method was not forget to implements. The same is also valid for setter and getter or add and remove.
But the compiler should inline this method.
The Java compiler does very few optimisations at compile time.
Instead the JIT does most of the optimisations at runtime based on how the applciation is actually used. It can inline methods, even up to two "virtual" methods.
No java does not. It's not a meaningful concept on Java.
As for the discussion of hashCode versus equals, some IDE and style checkers will warn you about mistakes like this, but I don't see that it has anything to do with 'inline'.
I don't think this can be inlined during compilation in Java, as all functions in Java are virtual, and you don't know until runtime which method is actually called, it might be the one of a subclass.
However, I don't think you need to worry about these things, because the HotSpot compiler should be pretty good at optimizing code that gets called frequently, on-the-fly, as the application is running.
Marking a method as final gives the JIT compiler a big hint as to how it can treat this method. You cannot force it to inline the method, but giving the JIT more explicit information can only help.
The consensus seems to be that there is a performance benefit to marking member variables as final because they never need reloading from main memory. My question is, do javac or Hotspot automatically do this for me when it's obvious the variable cannot change. eg will javac make 'x' final in this class below...
public class MyClass {
private String x;
MyClass(String x) {
this.x = x;
}
public String getX() {
return x;
}
}
On a secondary point, has anyone produced empirical evidence that marking members as final makes code run faster? Any benefit is surely negligible in any application making remote calls or database lookups?
Like many performance "enhancements" it is usually a better to ask; What is easier to understand and reason about? e.g. if a field is final I know it won't be changed anywhere. This is often leads to more optimial code, but more importantly it should be more maintainable code. ;)
Certainly, I make any field which can be final as final. Personally I would have preferred that final be the default behaviour and you had to use a keyword like var to make it mutable.
Allowing javac to do this would be a blunder. As there might be code in a different jar which may rely on the code being compiled (modularity), changing code at compile time for optimization sake is not a feasible option.
As for the second argument "never need reloading from the main memory", one needs to remember that most instance variables are cached. final only indicates immutability, it does not guarantee volatility (volatile == always get latest from main memory). Hence the need for locks and volatile keyword in multi-threaded environment.
As for the case with hotspot, I have no clue, and would like to hear more about it. final constants may be in-lined at compile time, thus allowing moderate performance gains. Reference to a question on in-lining in java
Edit: Note that final indicates immutability needs to be taken with a grain of salt. It does not guarantee that the state cannot change, it only specifies that the object reference can be modified. final indicates immutability for primitive data types
AFAIK, they do not, and thus, you suffer minor penalty. This, however, can be done automatically with IDE tools like Eclipse "Cleanup" feauture.
I believe a modern JVM (the Hotspot compiler) does detect that the value doesn't change, so there is no performance benefit in making parameters or variables final yourself. (If this is wrong, please provide a link or test case.) There is one exception: constants (static final).
However, this may be different with final methods and classes. It may improve performance in this case (I'm not completely sure in what cases). By the way, what does improve performance a little bit is making functions static (if possible).
The problem I have with final is that it clutters the code. It would be nice if final would be the default.
Is there a concept of inline functions in java, or its replaced something else? If there is, how is it used? I've heard that public, static and final methods are the inline functions. Can we create our own inline function?
In Java, the optimizations are usually done at the JVM level. At runtime, the JVM perform some "complicated" analysis to determine which methods to inline. It can be aggressive in inlining, and the Hotspot JVM actually can inline non-final methods.
The java compilers almost never inline any method call (the JVM does all of that at runtime). They do inline compile time constants (e.g. final static primitive values). But not methods.
For more resources:
Article: The Java HotSpot Performance Engine: Method Inlining Example
Wiki: Inlining in OpenJDK, not fully populated but contains links to useful discussions.
No, there is no inline function in java. Yes, you can use a public static method anywhere in the code when placed in a public class. The java compiler may do inline expansion on a static or final method, but that is not guaranteed.
Typically such code optimizations are done by the compiler in combination with the JVM/JIT/HotSpot for code segments used very often. Also other optimization concepts like register declaration of parameters are not known in java.
Optimizations cannot be forced by declaration in java, but done by compiler and JIT. In many other languages these declarations are often only compiler hints (you can declare more register parameters than the processor has, the rest is ignored).
Declaring java methods static, final or private are also hints for the compiler. You should use it, but no garantees. Java performance is dynamic, not static. First call to a system is always slow because of class loading. Next calls are faster, but depending on memory and runtime the most common calls are optimized withinthe running system, so a server may become faster during runtime!
Java does not provide a way to manually suggest that a method should be inlined. As #notnoop says in the comments, the inlining is typically done by the JVM at execution time.
What you said above is correct. Sometimes final methods are created as inline, but there is no other way to explicitly create an inline function in java.
Well, there are methods could be called "inline" methods in java, but depending on the jvm. After compiling, if the method's machine code is less than 35 byte, it will be transferred to a inline method right away, if the method's machine code is less than 325 byte, it could be transferred into a inline method, depending on the jvm.
Real life example:
public class Control {
public static final long EXPIRED_ON = 1386082988202l;
public static final boolean isExpired() {
return (System.currentTimeMillis() > EXPIRED_ON);
}
}
Then in other classes, I can exit if the code has expired. If I reference the EXPIRED_ON variable from another class, the constant is inline to the byte code, making it very hard to track down all places in the code that checks the expiry date. However, if the other classes invoke the isExpired() method, the actual method is called, meaning a hacker could replace the isExpired method with another which always returns false.
I agree it would be very nice to force a compiler to inline the static final method to all classes which reference it. In that case, you need not even include the Control class, as it would not be needed at runtime.
From my research, this cannot be done. Perhaps some Obfuscator tools can do this, or, you could modify your build process to edit sources before compile.
As for proving if the method from the control class is placed inline to another class during compile, try running the other class without the Control class in the classpath.
so, it seems there arent, but you can use this workaround using guava or an equivalent Function class implementation, because that class is extremely simple, ex.:
assert false : new com.google.common.base.Function<Void,String>(){
#Override public String apply(Void input) {
//your complex code go here
return "weird message";
}}.apply(null);
yes, this is dead code just to exemplify how to create a complex code block (within {}) to do something so specific that shouldnt bother us on creating any method for it, AKA inline!
Java9 has an "Ahead of time" compiler that does several optimizations at compile-time, rather than runtime, which can be seen as inlining.