Java Reference
In-Depth Information
It is possible that this variable came from some other classloader far away, or that it was somehow
gamed into existence. The bootstrap method, however, is going to need access to the class, and is going to
need it to be fully formed. To ensure that the class is fully loaded and accessible in the current context, we
will call the
Object.getClass()
method on
System.out
. The
invokevirtual
call, however, will consume
the top element of the stack as the target, and we want to keep the top element around - it's our reference
to
System.out
. So we first do a
dup
, which duplicates the top element of the stack. The stack now has two
System.out
references, and we consume one with
invokevirtual
to call the
Object.getClass()
method.
We don't want to actually do anything with the class, however, so we can then just
pop
it off the stack.
This class maneuver is the kind of bookkeeping that you do not have to deal with in the world of Java,
and which the compiler provides to you free of charge. It also demonstrates the subtlety and complexity of
bootstrapping and method handle lookups, which it is very easy to get wrong. So please love and appreciate
your compiler!
Free Instance Method References in Bytecode
There is one last kind of method reference: the free instance method reference. This is the case when we
pass in a type and an instance method to the method reference, and it creates a method that accepts that
type and calls the given instance method. This is somewhat like the bound method reference, in that it has to
track what type is being called. However, we do not have a particular instance that is being called in this case,
so it can't act like the bound instance method reference. How does it work?
To demonstrate this, we will create a method that will return the
BigInteger::toString
free instance
method reference. This free instance method reference requests a
BigInteger
to call, and returns a
String
.
The shape of this, therefore, is
Function<BigInteger,String>
. The resulting method and its abbreviated
bytecode is in Listing 8-4.
Listing 8-4.
Java Code for a Free Instance Method Reference with Its Bytecode (Abbreviated)
1 // Listing4.java, which is compiled to Listing4.class
2 import java.math.BigInteger;
3 import java.util.function.*;
4
5 public class Listing4 {
6 public static Function<BigInteger, String> getFunction() {
7 return BigInteger::toString;
8 }
9 }
10
11 // Abbreviated result of executing /usr/bin/javap -v -l -p -s -c Listing4 in the same
directory as Listing4.class
12 public class Listing4
13 BootstrapMethods:
14 0: #25 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(
Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/String;
Ljava/lang/invoke/MethodType;
Ljava/lang/invoke/MethodType;
Ljava/lang/invoke/MethodHandle;
Ljava/lang/invoke/MethodType;
)Ljava/lang/invoke/CallSite;