When to initialize the method's class for MethodHandles.Lookup.findStatic()?
David Holmes
david.holmes at oracle.com
Thu Mar 17 23:46:20 UTC 2022
Run with -Xlog:class+init=info to see the classes that get initialized
and in what order.
David
On 18/03/2022 5:53 am, Raffaello Giulietti wrote:
> 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