Cheng,

initialization is the last thing that happens because it's where user provided code gets executed.

This has always been this way, as long as I can remember. See the JVMS for the gory details.


Greetings
Raffaello


On 2022-03-18 01:21, Cheng Jin wrote:
Hi David,

1) for the test with mh.invoke() in main(),  the log shows:
[0.262s][info][class,init] Start class verification for: Test_1
[0.262s][info][class,init] End class verification for: Test_1
[0.263s][info][class,init] 282 Initializing 'Test_1' (0x0000000800c00800)
[0.263s][info][class,init] Start class verification for: Test_2
[0.263s][info][class,init] End class verification for: Test_2
[0.272s][info][class,init] 366 Initializing 'Test_2' (0x0000000800c00a08) 
<------

2) for the test without  mh.invoke() in main(),  the log shows:
[0.296s][info][class,init] Start class verification for: Test_1
[0.296s][info][class,init] End class verification for: Test_1
[0.297s][info][class,init] 282 Initializing 'Test_1' (0x0000000800c00800)
[0.297s][info][class,init] Start class verification for: Test_2
[0.297s][info][class,init] End class verification for: Test_2
(Test_2 was verified but didn't get initialized)

The comparison above literally surprised me that the bytecode verification 
happened prior to the class initialization, which means
the class got verified at first even without initialization coz I previously 
thought the initialization should trigger the verification rather than in the 
reversed order.

Could you explain a little more about why it goes in this way?

Best Regards
Cheng


-----Original Message-----
From: core-libs-dev <core-libs-dev-r...@openjdk.java.net> On Behalf Of David 
Holmes
Sent: March 17, 2022 7:46 PM
To: Raffaello Giulietti <raffaello.giulie...@gmail.com>; 
core-libs-dev@openjdk.java.net
Subject: [EXTERNAL] Re: When to initialize the method's class for 
MethodHandles.Lookup.findStatic()?

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
INVALID URI REMOVED
_en_java_javase_17_docs_api_java.base_java_lang_invoke_MethodHandles
.Lookup.html-23findStatic-28java.lang.Class-2Cjava.lang.String-2Cjav
a.lang.invoke.MethodType-29&d=DwIDaQ&c=jf_iaSHvJObTbx-siA1ZOg&r=X90f
3XIRXAH8hbNam6bIUlWfF_qUAezL9ue7M7bFuPQ&m=RvhguidNJ90V-HK-3Ctl-kUZE5
cIfo_nt3_r8VZ0Fcc&s=tw_ph6oUkS0eCvzITWi9zEkarss5yNeHDrAIfvd3s3g&e=
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

Reply via email to