As anyone who can answer this question will already know, the JVM supports several bytecode instructions for invoking methods (invokevirtual, invokespecial, invokestatic, ...)
Most method calls on instance methods are made by invokevirtual, but private methods and initializer methods are called via invokespecial, as described in the JVM spec:
The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes a method based on the class of the object. The invokespecial instruction is used to invoke instance initialization methods as well as private methods and methods of a superclass of the current class.
As I understand it, invokevirtual performs a vtable lookup to resolve the method while invokespecial, since the correct method implementation is known at link time, is resolved statically.
My question is, why is invokespecial not used to call public methods in cases where the concrete class of the method owner is known at compile-time? It seems to me that avoiding a vtable lookup would be desirable for efficiency reasons. But obviously there is something that I don't understand about the JVM.
First, it's not that easy to know the particular call target at compile time. JVM can load new classes dynamically and can even redefine the existing classes in runtime. A public method that appeared non-virtual at compile time may happen to become virtual in runtime.
You are right that vtable lookup can have a performance impact. However, invokevirtual bytecode does not imply vtable lookup at all.
For example, HotSpot JVM does its best to devirtualize method calls. It relies on Class Hierarchy Analysis and Runtime Type Profiles to translate invokevirtual to direct calls or, even better, to inline "virtual" methods directly into the call site. Only true megamorphic call sites (that have 3 or more targets in runtime) undergo a vtable lookup.
That said, with modern JVMs there is no performance difference between invokespecial and invokevirtual when the target method is actually non-virtual.
Related
I'm generating bytecode roughly equivalent to a class like:
final class MyCls {
final MethodHandle handle1;
final MethodHandle handle2;
// and so on
// This needs to invoke `handle1`, `handle2`, etc. in it somehow
final static myMethod() {
// ...
}
}
The class is fairly long-lived and I wish to call the MethodHandles from inside other methods, with ideally as little overhead as possible. What would be the best way to do this? The two ideas that come to mind are:
Generating explicit MethodHandle.invokeExact calls on the fields
Using invokedynamic somehow (although I think I'd still need the exactInvoker?)
The handles will vary in signatures (although their use-sites should all use the right signatures - I can detect/enforce that at codegen time).
Update
Here's some extra context on what I'm actually doing. The classes represent compiled WASM modules, the method handles are imported functions, and each instance of the class in another instance of the WASM module.
Using MethodHandle to represent imported functions isn't a necessity here - I could also accept something like a java.util.function.Function or maybe even just a virtual method invocation. I do need a MethodHandle representation sometimes, but I could summon one up from a virtual method too (and I could implement a virtual method manually calling a Function too).
The module class instances themselves might end up being stored in static fields but that's not guaranteed. If there is a way to speed up that case, I could recommend users use that.
The simple answer is to just generate invokeExact calls. With the code shape you've shown, there's no need to use invokedynamic (in fact that doesn't seem possible, since invokedynamic calls a bootstrap method which supplies the implementation dynamically).
Since the handles are stored instance fields, they are not seen as constants, and so the calls will be out of line, which adds overhead, as well as missed optimization opportunities due to a lack of inlining.
If you really want this to be as fast as possible, you'd need to generate a new class per combination of method handles you want to use, and store the method handles in static final fields, or in the constant pool (for instance using constant pool patching, or hidden classes + class data + dynamic constants [1]).
TL;DR
Please provide a piece of code written in some well known dynamic language (e.g. JavaScript) and how that code would look like in Java bytecode using invokedynamic and explain why the usage of invokedynamic is a step forward here.
Background
I have googled and read quite a lot about the not-that-new-anymore invokedynamic instruction which everyone on the internet agrees on that it will help speed dynamic languages on the JVM. Thanks to stackoverflow I managed to get my own bytecode instructions with Sable/Jasmin to run.
I have understood that invokedynamic is useful for lazy constants and I also think that I understood how the OpenJDK takes advantage of invokedynamic for lambdas.
Oracle has a small example, but as far as I can tell the usage of invokedynamic in this case defeats the purpose as the example for "adder" could much simpler, faster and with roughly the same effect expressed with the following bytecode:
aload whereeverAIs
checkcast java/lang/Integer
aload whereeverBIs
checkcast java/lang/Integer
invokestatic IntegerOps/adder(Ljava/lang/Integer;Ljava/lang/Integer;)Ljava/lang/Integer;
because for some reason Oracle's bootstrap method knows that both arguments are integers anyway. They even "admit" that:
[..]it assumes that the arguments [..] will be Integer objects. A bootstrap method requires additional code to properly link invokedynamic [..] if the parameters of the bootstrap method (in this example, callerClass, dynMethodName, and dynMethodType) vary.
Well yes, and without that interesing "additional code" there is no point in using invokedynamic here, is there?
So after that and a couple of further Javadoc and Blog entries I think that I have a pretty good grasp on how to use invokedynamic as a poor replacement when invokestatic/invokevirtual/invokevirtual or getfield would work just as well.
Now I am curious how to actually apply the invokedynamic instruction to a real world usecase so that it actually is some improvements over what we could with "traditional" invocations (except lazy constants, I got those...).
Actually, lazy operations are the main advantage of invokedynamic if you take the term “lazy creation” broadly. E.g., the lambda creation feature of Java 8 is a kind of lazy creation that includes the possibility that the actual class containing the code that will be finally invoked by the invokedynamic instruction doesn’t even exist prior to the execution of that instruction.
This can be projected to all kind of scripting languages delivering code in a different form than Java bytecode (might be even in source code). Here, the code may be compiled right before the first invocation of a method and remains linked afterwards. But it may even become unlinked if the scripting language supports redefinition of methods. This uses the second important feature of invokedynamic, to allow mutable CallSites which may be changed afterwards while supporting maximal performance when being invoked frequently without redefinition.
This possibility to change an invokedynamic target afterwards allows another option, linking to an interpreted execution on the first invocation, counting the number of executions and compiling the code only after exceeding a threshold (and relinking to the compiled code then).
Regarding dynamic method dispatch based on a runtime instance, it’s clear that invokedynamic can’t elide the dispatch algorithm. But if you detect at runtime that a particular call-site will always call the method of the same concrete type you may relink the CallSite to an optimized code which will do a short check if the target is that expected type and performs the optimized action then but branches to the generic code performing the full dynamic dispatch only if that test fails. The implementation may even de-optimize such a call-site if it detects that the fast path check failed a certain number of times.
This is close to how invokevirtual and invokeinterface are optimized internally in the JVM as for these it’s also the case that most of these instructions are called on the same concrete type. So with invokedynamic you can use the same technique for arbitrary lookup algorithms.
But if you want an entirely different use case, you can use invokedynamic to implement friend semantics which are not supported by the standard access modifier rules. Suppose you have a class A and B which are meant to have such a friend relationship in that A is allowed to invoke private methods of B. Then all these invocations may be encoded as invokedynamic instructions with the desired name and signature and pointing to a public bootstrap method in B which may look like this:
public static CallSite bootStrap(Lookup l, String name, MethodType type)
throws NoSuchMethodException, IllegalAccessException {
if(l.lookupClass()!=A.class || (l.lookupModes()&0xf)!=0xf)
throw new SecurityException("unprivileged caller");
l=MethodHandles.lookup();
return new ConstantCallSite(l.findStatic(B.class, name, type));
}
It first verifies that the provided Lookup object has full access to A as only A is capable of constructing such an object. So sneaky attempts of wrong callers are sorted out at this place. Then it uses a Lookup object having full access to B to complete the linkage. So, each of these invokedynamic instructions is permanently linked to the matching private method of B after the first invocation, running at the same speed as ordinary invocations afterwards.
I am using AspectJ and Load-time weaving to trace methods calls in an arbitrary java program. I can trace all calls using the standard:
call(* *.*(..))
But what I now trying to do is separate out calls to the native java libraries and any application code:
nativeCalls(): !within(MethodTracer) && call(* java..*.*(..));
appCalls(): !within(MethodTracer) && call(* *.*(..)) && !call(* java..*.*(..));
The issue is that the nativeCalls() pointcut is picking out calls to application classes that inherit from native java classes, even though the signatures do not start with java.lang. or java.util, etc.
For example:
If I have a class tetris.GameComponent that inherits from java.awt.Component, my nativeCalls() pointcut will pick out tetris.GameComponent.getBackground() when the method is actually implemented in java.awt.Component.getBackground().
Is there a way to have my nativeCalls() pointcut ignore the calls to inherited methods?
I hope this is clear. I can provide additional info if necessary. Thanks for any help that can be provided.
Actually I have no idea why you want to exclude those inherited method calls from your trace because IMO it is important or at least interesting to know if a method was called on one of your classes, even if that method was defined in a JDK super class.
But anyway, the answer is no, you cannot exclude calls to JDK methods from your nativeCalls() pointcut if those calls are actually made upon target objects typed to one of your application classes. At the time the call is made, AspectJ does not know how the JVM will resolve the polymorphism. There can be several cases:
Call to Foo.aaa(), existing method Foo.aaa() is executed. This is the simple case where a called method actually exists.
Call to Foo.bbb(), inherited method Base.bbb() is executed (polymorphism). This is the case you want to exclude, but you cannot because the fact that a base method is called will only be known when the method is executed. Furthermore, if Base is a JDK class, you cannot even intercept its method executions with AspectJ.
Call to Base.ccc(), non-overridden method Base.ccc() is executed. This can happen if you directly create an instance of Base or also if you assign/cast a Foo instance to a variable typed Base, e.g. Base obj = new Foo(), and call obj.ccc() which has not been overridden by Foo.
Call to Base.ddd(), overridden method Foo.ddd() is executed (polmorphism). This also happens if you assign/cast a Foo instance to a variable typed Base, e.g. Base obj = new Foo(), and call obj.ddd() which has been overridden by Foo.
So much for not being able to easily exclude the polymorphism stuff when calling inherited JDK method.
Now the other way around: You can easily intercept execution() instead of call() upon your application classes and take advantage of the fact that JDK method executions cannot be intercepted anyway: pointcut appMethod() : execution(* *(..));
Both instructions use static rather than dynamic dispatch. It seems like the only substantial difference is that invokespecial will always have, as its first argument, an object that is an instance of the class that the dispatched method belongs to. However, invokespecial does not actually put the object there; the compiler is the one responsible for making that happen by emitting the appropriate sequence of stack operations before emitting invokespecial. So replacing invokespecial with invokestatic should not affect the way the runtime stack / heap gets manipulated -- though I expect that it will cause a VerifyError for violating the spec.
I'm curious about the possible reasons behind making two distinct instructions that do essentially the same thing. I took a look at the source of the OpenJDK interpreter, and it seems like invokespecial and invokestatic are handled almost identically. Does having two separate instructions help the JIT compiler better optimize code, or does it help the classfile verifier prove some safety properties more efficiently? Or is this just a quirk in the JVM's design?
Disclaimer: It is hard to tell for sure since I never read an explicit Oracle statement about this, but I pretty much think this is the reason:
When you look at Java byte code, you could ask the same question about other instructions. Why would the verifier stop you when pushing two ints on the stack and treating them as a single long right after? (Try it, it will stop you.) You could argue that by allowing this, you could express the same logic with a smaller instruction set. (To go further with this argument, a byte cannot express too many instructions, the Java byte code set should therefore cut down wherever possible.)
Of course, in theory you would not need a byte code instruction for pushing ints and longs to the stack and you are right about the fact that you would not need two instructions for INVOKESPECIAL and INVOKESTATIC in order to express method invocations. A method is uniquely identified by its method descriptor (name and raw argument types) and you could not define both a static and a non-static method with an identical description within the same class. And in order to validate the byte code, the Java compiler must check whether the target method is static nevertheless.
Remark: This contradicts the answer of v6ak. However, a methods descriptor of a non-static method is not altered to include a reference to this.getClass(). The Java runtime could therefore always infer the appropriate method binding from the method descriptor for a hypothetical INVOKESMART instruction. See JVMS §4.3.3.
So much for the theory. However, the intentions that are expressed by both invocation types are quite different. And remember that Java byte code is supposed to be used by other tools than javac to create JVM applications, as well. With byte code, these tools produce something that is more similar to machine code than your Java source code. But it is still rather high level. For example, byte code still is verified and the byte code is automatically optimized when compiled to machine code. However, the byte code is an abstraction that intentionally contains some redundancy in order to make the meaning of the byte code more explicit. And just like the Java language uses different names for similar things to make the language more readable, the byte code instruction set contains some redundancy as well. And as another benefit, verification and byte code interpretation/compilation can speed up since a method's invocation type does not always need to be inferred but is explicitly stated in the byte code. This is desirable because verification, interpretation and compilation are done at runtime.
As a final anecdote, I should mention that a class's static initializer <clinit> was not flagged static before Java 5. In this context, the static invocation could also be inferred by the method's name but this would cause even more run time overhead.
There are the definitions:
http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc6.html#invokestatic
http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc6.html#invokespecial
There are significant differences. Say we want to design an invokesmart instruction, which would choose smartly between inkovestatic and invokespecial:
First, it would not be a problem to distinguish between static and virtual calls, since we can't have two methods with same name, same parameter types and same return type, even if one is static and second is virtual. JVM does not allow that (for a strange reason). Thanks raphw for noticing that.
First, what would invokesmart foo/Bar.baz(I)I mean? It may mean:
A static method call foo.Bar.baz that consumes int from operand stack and adds another int. // (int) -> (int)
An instance method call foo.Bar.baz that consumes foo.Bar and int from operand stack and adds int. // (foo.Bar, int) -> (int)
How would you choose from them? There may exist both methods.
We may try to solve it by requiring foo/Bar.baz(Lfoo/Bar;I) for the static call. However, we may have both public static int baz(Bar, int) and public int baz(int).
We may say that it does not matter and possibly disable such situation. (I don't think that it is a good idea, but just to imagine.) What would it mean?
If the method is static, there are probably no additional restrictions. On the other hand, if the method is not static, there are some restrictions: "Finally, if the resolved method is protected (§4.6), and it is either a member of the current class or a member of a superclass of the current class, then the class of objectref must be either the current class or a subclass of the current class."
There are some further differences, see the note about ACC_SUPER.
It would mean that all the referenced classes must be loaded before bytecode verification. I hope this is not necessary now, but I am not 100% sure.
So, it would mean very inconsistent behavior.
When programming C++ we used to create copy constructors when needed (or so we were taught). When switching to Java a few years ago, I noticed that the Cloneable interface is now being used instead. C# followed the same route defining the ICloneable interface. It seems to me that cloning is part of the definition of OOP. But I wonder, why were these interfaces created, and the copy constructor seems to have been dropped?
When I thought about it, I came to the thought that a copy constructor would not be useful if one needs to make a copy of an object whose type is not known (as in having a reference to a base type). This seems logical. But I wonder whether there are other reasons that I do not know of, for which the Cloneable interfaces have been favored over copy constructors?
I think it's because there is no such inherent need for a copy constructor in Java and in C# for reference types. In C++ objects are named. You can (and you will most often) copy (and in C++1x move) them around e.g when returning from functions, since returning pointers require you to allocate dynamic memory which would be slow and painful to manage. The syntax is T(x) so it makes sense to make a constructor taking a T reference. C++ couldn't make a clone function, since that would require returning an object by value again (and thus another copy).
But in Java, objects are unnamed. There are only references to them, which can be copied, but the object itself isn't copied. For the cases when you actually need to copy them, you can use the clone call (but i read in other anwers clone is flawed. i'm no java programmer so i cannot comment that). Since not the object itself is returned, but rather a reference to it, a clone function will suffice. Also a clone function can be overriden. That's not going to work with copy constructors. And incidentally, in C++ when you need to copy a polymorphic object, a clone function is required too. It's got a name, the so-called virtual copy constructor.
Because C++ and Java (and C#) aren't the same thing. C++ has no built-in interfaces because interfaces aren't part of the language. You can fake them with abstract classes but they aren't how you think about C++. Also, in C++ assignment is normally deep.
In Java and C# assignment just involves copying the handle to the internal object. Basically when you see:
SomeClass x = new SomeClass();
in Java or C#, there's a level of indirection builtin that doesn't exist in C++. In C++, you write:
SomeClass* x = new SomeClass();
Assignment in C++ involves the dereferenced value:
*x = *another_x;
In Java you can get access to the "real" object as there is no dereference operator like *x. So to do a deep copy, you need a function: clone(). And both Java and C# wrapped that function into an interface.
It's the issues of final type and of cascading the clone operation through the super classes which is not addressed by copy constructors - they are not extensible. But the Java clone mechanism is widely considered badly broken too; especially problems where a subclass does not implement clone(), but inherits from a superclass that implements cloneable.
I strongly recommend you research cloning carefully, whatever path you choose - you will likely choose the clone() option, but make sure you know exactly how to do it properly. It's rather like equals() and hashCode() - looks simple on the surface, but it has to be done exactly right.
I think you haven't get the right point. I give you my two cents.
Fundamentally there's a problem: creating a clone of a class without knowing the exact class type. If you use copy constructor, you cannot.
Here is an example:
class A {
public A(A c) { aMember = c.aMember }
int aMember;
}
class B : A {
public B(B c) : base(c) { bMember = c.bMember }
int bMember;
}
class GenericContainer {
public GenericContainer(GenericContainer c) {
// XXX Wrong code: if aBaseClass is an instance of B, the cloned member won't
// be a B instance!
aBaseClass = new A(c.aBaseClass);
}
A aBaseClass;
}
The Clone method, if declare virtual, could create the right class instance of the generic member.
An this problem is common to every language, C# C++ or Java...
Maybe this is what you was meaning, but I cannot understand this from any answer.
Just wanted to add that in Java the copy constructor is not completely useless.
There are cases where your class has a private instance variable of a mutable non-final type, e.g. Date, and has a setter and getter for the variable. In the setter, you should make a copy of the given date, because the caller could modify it later and thereby manipulate your object's internal state (usually by accident, but maybe intentional). In the getter, the same precaution is required.
The defensive copy could be implemented by calling clone() (the class Date is cloneable), but a malicious caller could call the setter with a subclass of Date which overrides the clone() method with {return this;}, and so the caller might still be able to manipulate your object. This is where the copy constructor comes into play: By calling new Date(theDate), you are sure to get a fresh Date instance with the same timestamp as the given date, without any connection between the two date instances. In the getter, you could use the clone method, because you know the private variable will be of class Date, but for consistency, usually the copy constructor is used there, too.
Also note that the copy constructor would note be required if the Date class was final (calling clone() were safe) or immutable (no copy required).
I think its only because once u have defined a copy constructor, you could never pass the reference itself again. (Unless it would have a function that does that...but thats not any easier than using the clone() method.)
In C++ its not a problem: you can pass the whole object or its reference.