invoke-custom
+
+ Starting from DEX version 038, the invoke-custom
instruction
+ was introduced to enable flexible, dynamic invocation of methods. It plays
+ a crucial role in dynamic method handling, particularly useful for lambda
+ expressions and functional programming in Java and allows Dalvik VM to
+ dynamically call methods at runtime by referencing a "call
+ site", which points to specific runtime metadata defining the method
+ to be called. In simple terms, invoke-custom
makes it
+ possible to execute methods that are not directly known or accessible at
+ compile time but are defined dynamically when the application runs. This
+ dynamic invocation mechanism aligns with Java's
+ java.lang.invoke
API and provides key support for features like
+ lambda expressions.
+
+ Instruction Syntax and Structure +
+Here’s a basic outline of the syntax:
+-
+
-
+
{`{vC, vD, vE, vF, vG}`}
: Registers containing arguments + passed to the invoked method. +
+ -
+
call_site@BBBB
: Reference to a "call site" in the + DEX file (identified by the indexBBBB
), which points to a + method and the metadata required for invocation. +
+
Each invoke-custom
instruction has the following fields:
-
+
- + Argument word count (4 bits): Specifies the number of + arguments for the method. + +
-
+ Call site reference index (16 bits): An index pointing
+ to the
call_site_item
in the DEX file, which contains all the + metadata for the invocation. +
+ - + Argument registers: Up to five registers that hold the + method's arguments. + +
+ The Role of call_site_item
+
+
+ call_site_item
is a special DEX structure used to hold metadata
+ about a call site. It's located in the DEX file's data section and
+ contains details about the method to be invoked, including the following:
+
-
+
-
+ Bootstrap Method Handle: A reference to a
+ "bootstrap" method that sets up the call site. This method
+ typically belongs to classes like
LambdaMetafactory
in Java + and must return ajava.lang.invoke.CallSite
. +
+ - + Method Name: A string representing the name of the + method to be resolved. + +
- + Method Type: A descriptor defining the method’s + argument and return types. + +
+ This setup gives invoke-custom
the information needed to invoke
+ a method dynamically.
+
+ Example of a call_site_item
+
+
+ Here’s what a typical call_site_item
would look like conceptually:
+
+ Additional arguments can also be included as constant values, passed to + the bootstrap method in order. +
+
+ Execution Phases of invoke-custom
+
+
+ The invoke-custom
instruction executes in two main phases:
+
-
+
-
+
Call Site Resolution:
+-
+
-
+ The DEX interpreter checks if there’s an existing
CallSite
object for the specified call site. +
+ -
+ If a
CallSite
doesn’t exist, the bootstrap method + specified incall_site_item
is invoked with the + provided arguments. This bootstrap method returns a +CallSite
object that represents the method to be called. +
+ -
+ The
CallSite
object is cached for future calls to improve + performance. +
+
+ -
+ The DEX interpreter checks if there’s an existing
-
+
Call Site Invocation:
+-
+
-
+ After the
CallSite
is resolved, the +MethodHandle
+ within theCallSite
is invoked. +
+ -
+ This invocation works similarly to the
invoke-polymorphic
+ instruction, where the arguments passed in the +invoke-custom
instruction are used directly. +
+
+ -
+ After the
+ Practical Example: invoke-custom
in Action
+
+
+ Consider this Java code in the ApkSplitInfoCleaner
+
class:
+
+ In bytecode, this invocation of isSplitMetaElement
as a
+ lambda will be compiled into an invoke-custom
call, where the
+ DEX file contains a call_site_item
that references
+ LambdaMetafactory.metafactory
to create a lambda expression.
+
Bytecode Example
+Here’s what this might look like in Dalvik bytecode:
+This example showcases the following:
+-
+
-
+
call_site_2
defines the arguments for the +LambdaMetafactory.metafactory
bootstrap method. +
+ -
+ The bootstrap method generates a
CallSite
instance, + enabling theisSplitMetaElement
method to be invoked as a lambda + expression matching a functional interface. +
+
invoke-polymorphic
+
+ invoke-polymorphic
is another bytecode instruction (Also
+ introduced starting from DEX version 038 onwards) similar to
+ invoke-custom
, but it's specifically used for invoking
+ MethodHandle
+ methods like invoke
or invokeExact
. While
+ invoke-custom
+ is for more general dynamic invocation, invoke-polymorphic
is
+ restricted to methods directly supporting polymorphic invocation in
+ MethodHandle
.
+