DEV Community

Pramoth Suwanpech
Pramoth Suwanpech

Posted on

Java InvokeDynamic (part 2 CallSite)

ในตอนนี้เราจะ เข้าไปใกล้ invokedynamic เพิ่มขึ้นอีกนิด
จาก part 1 เราได้เห็นวิธีการเรียก method ด้วย MethodHandle.invoke*() ไปแล้ว ในตอนนี้เราจะมาอธิบายการทำงานของ invokedynamic ในรูปแบบ java api และบทความถัดไปจะทดลองทำให้ดูในรูปแบบ bytecode โดยใช้ ASM

invokespecial,invokestatic จะ resolve target method โดยตรงจาก class
invokevirtual,invokeinterface จะ resolve target method จาก virtual method table

invoke** ด้านบนทั้งหมดจะมีกฏตายตัวในการ resove target method แต่สำหรับ invokedynamic จะ delegate การ resolve target method ไปให้เป็นหน้าที่ของ bootstrap method เพื่อเปิดโอกาสที่ผู้ที่อิมพรีเมนภาษาต่างๆสามารถ customize logic ในการ resolve method เองได้

bootstrap method จะ associate กับ invokedynamic instruction หรือพูดได้ว่า invokedynamic จะเรียก bootstrap method เพื่อให้มันรีเทิร์น java.lang.invoke.CallSite กลับมาให้ ซึ่งใน CallSite ก็จะมี target (CallSite.getTarget()) ที่เป็น MethodHandle ที่จะเป็น target method ที่เราต้องการให้เรียกอีกที
การเรียก bootstrap method สามารถคืนค่า MethodHandle เดิมเมือ่เรียกครั้งถัดไปหรืออาจจะไม่คืนค่าเดิมก้ได้ โดย CallSite จะมีสองแบบ constant และ mutable และเราสามารถสร้าง bootstrap method สำหรับแต่ละคำสั่ง invokedynamic หรือจะแชร์ bootstrap method กันก็ได้

invokedynamic จะมีรุปแบบดังนี้

invokedynamic boostrap-method-ref:[method-name:method-type]

โดย

  • boostrap-method-ref จะอ้างถึง BootstrapMethod attribute ใน constant pool
  • [method-name : method-type] จะอ้างถึง NameAndType_info ใน constant pool ซึ่ง method-name จะเป็นชื่อ target method และ method-type จะเป็น args และ return type

bootstrap method จะมีหลายรูปแบบ (สามารถอ่านเพิ่มเติมจาก JSR-292) การเรียก bootstrap method จะมีการระบุ parameter อย่างน้อย 3 ตัว ตามตัวอย่างนี้

CallSite bootstrap(Lookup caller, String name, MethodType type)

การทำงานของ invokedynamic จะทำงานหลักๆอยู่ 3 step สรุปโดยย่อจาก 6.5.invokedynamic

  1. prepare parameter Lookup,name,MethodType (name,MethodType จะ resove reference จาก constant pool แต่ Lookup ผมไม่ทราบ ไม่ได้มีอธิบายไว้ ถ้าดูจากโคีด มันจะใช้ Reflection.getCallerClass() ซึ่งเป็น native method)
  2. link คือขั้นตอนการเรียก bootstrap method
  3. invoke

เด๋วจะขอยกตัวอย่างการจำลองการ invokedynamic โดย java api เลยละกันครับ

public class MethodHandleTest2 {
    public static void main(String[] args) throws Throwable {
        // บรรทัดถัดไปคือ bytecode ของ invokedynamic นะครับ #1 #2 #3  จะถูกเก็บไว้ใน constant pool
        // invokedynamic #1:[#2:#3]

        // step 1 preapre อันนี้ทำโดย JVM
        final MethodHandles.Lookup callerLookup = MethodHandles.lookup();
        // #2
        String targetMethodName = "target";
        // #3
        MethodType methodType = MethodType.methodType(void.class, String.class);


        // step 2 link
        CallSite callSite = boostrapMethod(callerLookup, targetMethodName, methodType);


        // step 3 invoke
        // ในเคสของ ConstantCallSite dynamicInvoker() จะ delegate ไป getTarget()
        callSite.dynamicInvoker().invokeWithArguments("world"); // print "Hello world"

    }

    // #1
    private static CallSite boostrapMethod(MethodHandles.Lookup callerContextLookup, String name, MethodType methodType) throws NoSuchMethodException, IllegalAccessException {
        final MethodHandle methodHandle = callerContextLookup.findStatic(callerContextLookup.lookupClass(), name, methodType);
        CallSite callSite = new ConstantCallSite(methodHandle);
        return callSite;
    }

    //target method  ของเรา มี type description (Ljava/lang/String;)V
    private static void target(String msg) {
        System.out.println("Hello " + msg);
    }
}

reference:
Constant Pool
invokedynamic
JSR-292

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay