JIT optimization preventing techniques - java

In java-8 sources we can find quite tricky way of JIT optimization inside class Class:
/*
* Private constructor. Only the Java Virtual Machine creates Class objects.
* This constructor is not used and prevents the default constructor being
* generated.
*/
private Class(ClassLoader loader) {
// Initialize final field for classLoader. The initialization value of non-null
// prevents future JIT optimizations from assuming this final field is null.
classLoader = loader;
}
So, this constructor is never invoked, but JIT will be "cheated" by this trick.
My question is: could it be implemented in slightly different way, let's say
private Class() {
classLoader = (ClassLoader)(new Object());
}
This is absolutely meaningless logic, but does it matter if constructor will never been invoked?
Would such kind of trick also prevent JIT from this optimization?

In Java 6 and Java 7 (and Java 8 before update 40), the constructor is as simple as private Class() {}, but in these versions, there is no classLoader field either.
This implies that the association between Class and ClassLoader had to be maintained in a special JVM specific way, thus, getClassLoader() has to call into a native method, not necessarily involving JNI, but rather handled as a JVM intrinsic operation, but still requiring special care inside the JVM’s native code. Further, the garbage collector had to know about the special relationship.
In contrast, hiding a field in Reflection is not so complicated, while now having an ordinary field simplifies the JVM’s native code, most notably the getClassLoader() operation and the garbage collector implementation(s). It might also be simpler for the optimizer to inline field accesses if it’s an ordinary field.
Now, when the Class objects are created via special JVM code, not using the declared constructor, it could contradict an optimizing JIT’s assumptions made by analyzing the constructor’s actual code to predict the possible values for this final field.
Note that nobody said that the current JIT is that smart. The comment talks about hypothetical “future JIT optimizations”. Having a constructor initializing the field with a parameter value is in line with what the JVM actually does.
In contrast, a constructor like your suggested classLoader = (ClassLoader)(new Object()); could lead a hypothetical optimizer to conclude that this field can’t be initialized with an actual ClassLoader instance as that code can never complete normally.

The commentary in the source of Class states that the initialisation value make future JIT optimisation knowing that the classLoader field is not null. So the optimizer might do an even better job in future.
To prevent optimisation, just declare your fields volatile.

Related

Can I insert instructions in constructors before calling this() / super() and before initialising any final fields?

Preface
I have been experimenting with ByteBuddy and ASM, but I am still a beginner in ASM and between beginner and advanced in ByteBuddy. This question is about ByteBuddy and about JVM bytecode limitations in general.
Situation
I had the idea of creating global mocks for testing by instrumenting constructors in such a way that instructions like these are inserted at the beginning of each constructor:
if (GlobalMockRegistry.isMock(getClass()))
return;
FYI, the GlobalMockRegistry basically wraps a Set<Class<?>> and if that set contains a certain class, then isMock(Class<?>> clazz) would return true. The advantage of that concept is that I can (de)activate global mocking for each class during runtime because if multiple tests run in the same JVM process, one test might need a certain global mock, the next one might not.
What the if(...) return; instructions above want to achieve is that if mocking is active, the constructor should not do anything:
no this() or super() calls, → update: impossible
no field initialisations, → update: possible
no other side effects. → update: might be possible, see my update below
The result would be an object with uninitialised fields that did not create any (possibly expensive) side effects such as resource allocation (database connection, file creation, you name it). Why would I want that? Could I not just create an instance with Objenesis and be happy? Not if I want a global mock, i.e. mock objects I cannot inject because they are created somewhere inside methods or field initialisers I do not have control over. Please do not worry about what method calls on such an object would do if its instance fields are not properly initialised. Just assume I have instrumented the methods to return stub results, too. I know how to do that already, the problem are only constructors in the context of this question.
Questions / problems
Now if I try to simulate the desired result in Java source code, I meet the following limitations:
I cannot insert any code before this() or super(). I could mitigate that by also instrumenting the super class hierarchy with the same if(...) return;, but would like to know if I could in theory use ASM to insert my code before this() or super() using a method visitor. Or would the byte code of the instrumented class somehow be verified during loading or retransformation and then rejected because the byte code is "illegal"? I would like to know before I start learning ASM because I want to avoid wasting time for an idea which is not feasible.
If the class contains final instance fields, I also cannot enter a return before all of those fields have been initialised in the constructor. That might happen at the very end of a complex constructor which performs lots of side effects before actually initialising the last field. So the question is similar to the previous one: Can I use ASM to insert my if(...) return; before any fields (including final ones) are initialised and produce a valid class which I could not produce using javac and will not be rejected when loaded or retransformed?
BTW, if it is relevant, we are talking about Java 8+, i.e. at the time of writing this that would be Java versions 8 to 14.
If anything about this question is unclear, please do not hesitate to ask follow-up questions, so I can improve it.
Update after discussing Antimony's answer
I think this approach could work and avoid side effects, calling the constructor chain but avoiding any side effects and resulting in a newly initialised instance with all fields empty (null, 0, false):
In order to avoid calling this.getClass(), I need to hard-code the mock target's class name directly into all constructors up the parent chain. I.e. if two "global mock" target classes have the same parent class(es), multiple of the following if blocks would be woven into each corresponding parent class, one for each hard-coded child class name.
In order to avoid any side effects from objects being created or methods being called, I need to call a super constructor myself, using null/zero/false values for each argument. That would not matter because the next parent class up the chain would have a similar code block so that the arguments given do not matter anyway.
// Avoid accessing 'this.getClass()'
if (GlobalMockRegistry.isMock(Sub.class)) {
// Identify and call any parent class constructor, ideally a default constructor.
// If none exists, call another one using default values like null, 0, false.
// In the class derived from Object, just call 'Object.<init>'.
super(null, 0, false);
return;
}
// Here follows the original byte code, i.e. the normal super/this call and
// everything else the original constructor does.
Note to myself: Antimony's answer explains "uninitialised this" very nicely. Another related answer can be found here.
Next update after evaluating my new idea
I managed to validate my new idea with a proof of concept. As my JVM byte code knowledge is too limited and I am not used to the way of thinking it requires (stack frames, local variable tables, "reverse" logic of first pushing/popping variables, then applying an operation on them, not being able to easily debug), I just implemented it in Javassist instead of ASM, which in comparison was a breeze after failing miserably with ASM after hours of trial & error.
I can take it from here and I want to thank user Antimony for his very instructive answer + comments. I do know that theoretically the same solution could be implemented using ASM, but it would be exceedingly difficult in comparison because its API is too low level for the task at hand. ByteBuddy's API is too high level, Javassist was just right for me in order to get quick results (and easily maintainable Java code) in this case.
Yes and no. Java bytecode is much less restrictive than Java (source) in this regard. You can put any bytecode you want before the constructor call, as long as you don't actually access the uninitialized object. (The only operations allowed on an uninitialized this value are calling a constructor, setting private fields declared in the same class, and comparing it against null).
Bytecode is also more flexible in where and how you make the constructor call. For example, you can call one of two different constructors in an if statement, or you can wrap the super constructor call in a "try block", both things that are impossible at the Java language level.
Apart from not accessing the uninitialized this value, the only restriction* is that the object has to be definitely initialized along any path that returns from the constructor call. This means the only way to avoid initializing the object is to throw an exception. While being much laxer than Java itself, the rules for Java bytecode were still very deliberately constructed so it is impossible to observe uninitialized objects. In general, Java bytecode is still required to be memory safe and type safe, just with a much looser type system than Java itself. Historically, Java applets were designed to run untrusted code in the JVM, so any method of bypassing these restrictions was a security vulnerability.
* The above is talking about traditional bytecode verification, as that is what I am most familiar with. I believe stackmap verification behaves similarly though, barring implementation bugs in some versions of Java.
P.S. Technically, Java can have code execute before the constructor call. If you pass arguments to the constructor, those expressions are evaluated first, and hence the ability to place bytecode before the constructor call is required in order to compile Java code. Likewise, the ability to set private fields declared in the same class is used to set synthetic variables that arise from the compilation of nested classes.
If the class contains final instance fields, I also cannot enter a return before all of those fields have been initialised in the constructor.
This, however, is eminently possible. The only restriction is that you call some constructor or superconstructor on the uninitialized this value. (Since all constructors recursively have this restriction, this will ultimately result in java.lang.Object's constructor being called). However, the JVM doesn't care what happens after that. In particular, it only cares that the fields have some well typed value, even if it is the default value (null for objects, 0 for ints, etc.) So there is no need to execute the field initializers to give them a meaningful value.
Is there any other way to get the type to be instantiated other than this.getClass() from a super class constructor?
Not as far as I am aware. There's no special opcode for magically getting the Class associated with a given value. Foo.class is just syntactic sugar which is handled by the Java compiler.

Java Runtime constant pool reference variable in stack frame

According to the following link the java stack frame contains local variables, operand stack and the current class constant pool reference.
http://blog.jamesdbloom.com/JVMInternals.html
Also From Oracle "Structure of JVM" Section 2.6.3. "Dynamic Linking - Each frame (§2.6) contains a reference to the run-time constant pool (§2.5.5) for the type of the current method to support dynamic linking of the method code."
I have also read that the object in the heap also has a pointer/reference to the class data.
https://www.artima.com/insidejvm/ed2/jvm6.html
The stack frame will contain the "current class constant pool reference" and also it will have the reference to the object in heap which in turn will also point to the class data. Is this not redundant??
For example.
public class Honda {
public void run() {
System.out.println("honda is running");
}
public static void main(String[] args) {
Honda h = new Honda();
h.run(); //output honda is running
}
}
When h.run() is going to be executed, jvm will create a new stack frame and push h on the stack frame. h will point to the object in heap which in turn will have a pointer to class data of Honda. The stack frame will also have current class constant reference. Is this correct? If not please shed some light on this.
Is this not redundant??
Maybe it is redundant for instance methods and constructors.
It isn't redundant for static methods or class initialization pseudo-methods.
It is also possible that the (supposedly) redundant reference gets optimized away by the JIT compiler. (Or maybe it isn't optimized away ... because they have concluded that the redundancy leads to faster execution on average.) Or maybe the actual implementation of the JVM1 is just different.
Bear in mind that the JVM spec is describing an idealized stack frame. The actual implementation may be different ... provided that it behaves the way that the spec says it should.
On #EJP's point on normativeness, the only normative references for Java are the JLS and JVM specifications, and the Javadoc for the class library. You can also consult the source code of the JVM itself. The specifications say what should happen, and the code (in a sense) says what does happen. An article you might find in a published paper or a web article is not normative, and may well be incorrect or out of date.
1 - The actual implementation may vary from one version to the next, or between vendors. Furthermore, I have heard of a JVM implementation where a bytecode rewriter transformed from standard bytecodes to another abstract machine language at class load time. It wasn't a great idea from a performance perspective ... but it was certainly within the spirit of the JVM spec.
The stack frame will contain the "current class constant pool reference" and also it will have the reference to the object in heap which in turn will also point to the class data. Is this not redundant??
You missed the precondition of that statement, or you misquoted it, or it was just plainly wrong where you saw it.
The "reference to the object in heap" is only added for non-static method, and it refers to the hidden this parameter.
As it says in section "Local Variables Array":
The array of local variables contains all the variables used during the execution of the method, including a reference to this, all method parameters and other locally defined variables. For class methods (i.e. static methods) the method parameters start from zero, however, for instance method the zero slot is reserved for this.
So, for static methods, there is no redundancy.
Could the constant pool reference be eliminated when this is present? Yes, but then there would need to be a different way to locate the constant pool reference, requiring different bytecode instructions, so that would be a different kind of redundancy.
Always having the constant pool reference available in a well-known location in the stack frame, simplifies the bytecode logic.
There are two points here. First, there are static methods which are invoked without a this reference. Second, the actual class of an object instance is not necessarily the declaring class of the method whose code we are actually executing. The purpose of the constant pool reference is to enable resolving of symbolic references and loading of constants referenced by the code. In both cases, we need the constant pool of the class containing the currently executed code, even if the method might be inherited by the actual class of the this reference (in case of a private method invoked by another inherited method, we have a method invoked with a this instance of a class which formally does not even inherit the method).
It might even be the case that the currently executed code is contained in an interface, so we never have instances of it, but still a class file with a constant pool which must be available when executing the code. This does not only apply to Java 8 and newer, which allow static and default methods in interfaces; earlier versions also might need to execute the <clinit> method of an interface to initialize its static fields.
By the way, even if an instance method is invoked with an object reference associated with this in its first local variable, there is no requirement for the bytecode instructions to keep it there. If not needed, it might get overwritten by an arbitrary value, reusing the variable slot for other purposes. This does not preclude that subsequent instructions need the constant pool, which, as said, does not need to belong to the actual class of this anyway.
Of course, that pool reference is a logical construct anyway. Implementations may transform the code to use a shared pool or not to need a pool at all when all references have been resolved already, etc. After inlining, code may not even have a dedicated stack frame anymore.

Visibility of Methods and their cost

I recently read this article by Jake Wharton. This is targeted at Android, but also perfectly valid for java I think.
Consider the following code:
public class A {
private String someField = "abc";
class B {
public void doSomething() {
System.out.println(someField);
}
}
}
We have a simple class A and an inner class B (This has a reference to A and can acccess its members). Class B is accessing the field someField in A even though it is private. According to the article, this is done by the compiler generating synthetic accessor methods which allow the inner class to access the field.
Now my way more basic question: Why does the compiler even care about visiblities when the code is compiled? As we have seen in this example, a new method is generated, which basically just introduces overhead.
Visibilities are a great thing for architecting good software, but if the compiler is done checking that everything is correct according to the declared visibilies, why not optimize those methods away (E.g. just taking everything for being public and allow calls to it)?
First I thought this was due to security reasons, but reflection allows the access of all fields, not caring for visibility as far as I know.
This might be a basic misunderstanding of me, if so, I would be happy if someone could explain it to me.
Why does the compiler even care about visiblities when the code is compiled?
The JVM doesn't allows access to private methods/constructors/fields outside a class. It has no special rule for nested classes which were added after this rule was designed. Instead the compiler adds accessor methods so the language can support a means of access the JVM doesn't.
As we have seen in this example, a new method is generated, which basically just introduces overhead.
Only if the method isn't called very much and isn't optimised.
Adding any simple method (On Hotspot, any method of 35 bytes or less) will be inlined very quickly and has no impact on performance (except if the maximum inline level is reached)
why not optimize those methods away
It does this at runtime so that previous rules continue to be enforced.
reflection allows the access of all fields, not caring for visibility as far as I know.
Though not by default, you have to explicitly want this as an option and not have a SecurityManager which prevents it.
If compiler converts all private fields to public fields in compile time, one problem will be happened when your project is compiled into library and reused by others. In that case, all your private fields will become public.
There are some tools for optimizing this. In Android, there is a tool named ProGuard that will convert all getter/setter to direct field access.

Non-final methods in a final class

My question is pretty simple:
Does the compiler treat all the methods in a final class as being final themselves? Does adding the final keyword to methods in a final class has any effect?
I understood that final methods have a better chance of getting inlined and this is why I am asking.
Thanks in advance.
You're correct, all methods in a final class are implicitly final.
See here:
"Note that you can also declare an entire class final. A class that is
declared final cannot be subclassed. This is particularly useful, for
example, when creating an immutable class like the String class."
And here:
All methods in a final class are implicitly final.
This may also be of interest for you: Performance tips for the Java final keyword
Does the compiler treat all the methods in a final class as being final themselves?
In effect, yes it does. A method in a final class cannot be overridden. Adding (or removing) a final keyword to a method makes no difference to this rule.
Does adding the final keyword to methods in a final class has any effect?
In practice, it has minimal effect. It has no effect on the rules on overriding (see above), and no effect on inlining (see below).
It is possible to tell at runtime if a method was declared with a final keyword ... using reflection to look at the method's flags. So it does have some effect, albeit an effect that it irrelevant to 99.99% of programs.
I understood that final methods have a better chance of getting inlined and this is why I am asking.
This understanding is incorrect. The JIT compiler in a modern JVMs keeps track of which methods are not overridden in the classes loaded by an application. It uses this information, and the static types to determine whether a particular call requires virtual class dispatching or not. If not, then inlining is possible, and will be used depending on how large the method body is. In effect, the JIT compiler ignores the presence / absence of final, and uses a more accurate method to detect method calls where inlining of the method is allowable.
(In fact it is more complex than this. An application can dynamically load subclasses that cause the JIT compiler's method override analysis to become incorrect. If this happens, the JVM needs to invalidate any effected compiled methods and cause them to be recompiled.)
The bottom line is:
There is NO performance advantage in adding final to methods in final classes.
There might be a performance advantage in final to methods in non-final classes, but only if you are using an old Sun JVM, or some other Java / Java-like platform with a poor quality JIT compiler.
If you care about performance, it is better to use an up-to-date / high performance Java platform with a decent JIT compiler than to pollute your code-base with final keywords that are liable to cause you problems in the future.
You wrote in a comment:
#RussellZahniser I have read differently in many places.
The internet is full of old information, much of which is out of date ... or was never correct in the first place.
May be the compiler treats them as final.
The following prints "false":
final class FinalClass {
public void testMethod() {}
}
Method method = FinalClass.class.getDeclaredMethod("testMethod");
int m = method.getModifiers();
System.out.println(Modifier.isFinal(m));

Why defining class as final improves JVM performance?

Quoting from http://sites.google.com/site/gson/gson-design-document:
Why are most classes in Gson marked as
final?
While Gson provides a fairly
extensible architecture by providing
pluggable serializers and
deserializers, Gson classes were not
specifically designed to be
extensible. Providing non-final
classes would have allowed a user to
legitimately extend Gson classes, and
then expect that behavior to work in
all subsequent revisions. We chose to
limit such use-cases by marking
classes as final, and waiting until a
good use-case emerges to allow
extensibility. Marking a class final
also has a minor benefit of providing
additional optimization opportunities
to Java compiler and virtual machine.
Why is this the case? [If I would guess: of JVM knows class is final it does not maintain method override tables? Are there any other reasons?]
What is the benefit in performance?
Does this applies to classes that are frequency instantiated (POJO?) or perhaps to class that are holders static methods (Utility classes) ?
Are methods defined as final also can theoretically improve performance?
Are there any implications?
Thank you,
Maxim.
Virtual (overridden) methods generally are implemented via some sort of table (vtable) that is ultimately a function pointer. Each method call has the overhead of having to go through that pointer. When classes are marked final then all of the methods cannot be overridden and the use of a table is not needed anymore - this it is faster.
Some VMs (like HotSpot) may do things more intelligently and know when methods are/are not overridden and generate faster code as appropriate.
Here is some more specific info on HotSpot. And some general info too.
An old, apparently no longer but still largely relevant, article on this from IBM developerWorks, which states:
The common perception is that
declaring classes or methods final
makes it easier for the compiler to
inline method calls, but this
perception is incorrect (or at the
very least, greatly overstated).
final classes and methods can be a
significant inconvenience when
programming -- they limit your options
for reusing existing code and
extending the functionality of
existing classes. While sometimes a
class is made final for a good reason,
such as to enforce immutability, the
benefits of using final should
outweigh the inconvenience.
Performance enhancement is almost
always a bad reason to compromise good
object-oriented design principles, and
when the performance enhancement is
small or nonexistent, this is a bad
trade-off indeed.
Also see this related answer on another question. There's also the equivalent question for .Net, discussed here. SO discussion, "Are final methods inlined?" On a question titled "What optimizations are going to be useless tomorrow," this one appears on the list.
Note also that there is an entangling of the effects of final classes vs. final methods. You may get some performance benefit (again, I don't have a good reference) for final methods for sure, as it could cue the JIT to do inlining it couldn't otherwise do (or not so simply). You get the same effect when you mark the class final, which means that all the methods are suddenly final as well. Note that the Sun/Oracle folks claim that HotSpot can usually do this with or without the final keyword. Are there any additional effects from having the class itself final?
For reference, links to the JLS on final methods and final classes.
Not knowing the implementation of every particular JVM, I would theoretically say that if a JVM knows that a pointer to an object is a pointer to a type that is final, it can do non-virtual function calls (i.e., direct vs. indirect) to a member functions (i.e., no indirection through a function pointer), which may result in faster execution. This may also in turn lead to inlinining possibilities.
Marking classes as final allows further optimizations to be applied during the JIT stage.
If you are calling a virtual method on a non-final class, you don't know whether the proper implementation is the one defined in that class, or some sub-class that you don't know about.
However, if you have a reference to a final class, you know the specific implementation that is required.
Consider:
A extends B
B extends C
B myInstance = null;
if(someCondition)
myInstance = new B();
else
myInstance = new C();
myInstance.toString();
In this case, the JIT can't know whether C's implementation of toString() or B's implementation of toString() will be called. However, if B is marked as final, it is impossible for any implementation other than B's to be the proper implementation
No difference, that's just speculation. The only situation where it has sense are classes like String, etc where jvm treat them differently.

Categories