When to initialize the method's class for MethodHandles.Lookup.findStatic()?
Raffaello Giulietti
raffaello.giulietti at gmail.com
Thu Mar 17 19:53:57 UTC 2022
Hi again,
here's code that shows that initialization doesn't happen during lookup
but only upon invoking the method handle. (I'm on Java 17.)
As long as the 2nd line in main() is commented, you don't see the
message "Test_2 initialized", which shows that the lookup doesn't
initialize Test_2.
When you uncomment the line in main(), the message will appear.
So, as advertised, it's the invocation of the method handle that can
trigger initialization, not the lookup.
HTH
Raffaello
----
import java.lang.invoke.*;
public class Test_1 {
static MethodHandle mh;
static {
try {
mh = MethodHandles.lookup().findStatic(Test_2.class,
"testMethod", MethodType.methodType(int.class, int.class));
} catch (NoSuchMethodException | IllegalAccessException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Throwable {
System.out.println(mh);
// System.out.println(Test_1.mh.invoke(0));
}
}
public class Test_2 {
static {
System.out.println("Test_2 initialized");
}
static int testMethod(int value) { return (value + 1); }
}
On 2022-03-17 20:38, Raffaello Giulietti wrote:
> Hi,
>
> as far as I can see, the code should not even compile, as there's a
> static field in Test_1 which is initialized with an expression that
> throws checked exceptions (findStatic(..)).
>
> In addition, it seems to me that there's nothing in your code that
> reveals whether Test_2 has been initialized during the lookup. How can
> you tell?
>
> Finally, the method handle invocation in Test_1 will throw, as you don't
> pass any argument to a handle that expects one.
>
> Can you perhaps add more details?
>
>
> Greetings
> Raffaello
>
>
>
> On 2022-03-17 17:42, Cheng Jin wrote:
>> Hi there,
>>
>> The document of
>> https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html#findStatic(java.lang.Class,java.lang.String,java.lang.invoke.MethodType)
>> in the Java API is ambiguous in terms of when to initialize the
>> method's class as follows (the same description as in other OpenJDK
>> versions)
>>
>> If the returned method handle is invoked, the method's class will be
>> initialized, if it has not already been initialized.
>>
>>
>> It occurs to me that the method's class should be initialized when
>> invoking the method handle but OpenJDK actually chooses to do the
>> initialization in lookup.findStatic() rather than in mh.invoke()
>> e.g.
>> import java.lang.invoke.*;
>>
>> public class Test_1 {
>> static MethodHandle mh =
>> MethodHandles.lookup().findStatic(Test_2.class, "testMethod",
>> MethodType.methodType(int.class, int.class)); <-----------
>> Test_2.class gets initialized and verified.
>>
>> public static void main(String[] args) throws Throwable {
>> Test_1.mh.invoke();
>> }
>> }
>>
>> public class Test_2 {
>> static int testMethod(int value) { return (value + 1); }
>> }
>>
>> So there should be more clear explanation what is the correct or
>> expected behaviour at this point and why OpenJDK doesn't comply with
>> the document to delay the initialization of the method's class to
>> mh.invoke().
>>
>> Best Regards
>> Cheng Jin
More information about the core-libs-dev
mailing list