After some research, I came to some conclusions regarding my question, they were:
Regarding an example of in encoding java + javascript I could find in a reference of a answer by @Filipegonzagamiranda who was featured in the comments and was a great starting point.
Following I worked on a different example, more advanced, mixing java and javascript:
public class NashornEval {
public static void main(String... args) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
String js;
js = "var Thread = java.lang.Thread; \n";
js += "var map = Array.prototype.map \n";
js += "var names = [\"corinthians\", \"palmeiras\", \"santos\"]\n";
js += "var a = map.call(names, function(name) { return name.length() })\n";
js += "print(a); \n";
js += "Thread.sleep(5000); \n";
js += "print(\"finalizado...\");";
try {
engine.eval(js);
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
And it really worked!
11,9,6
(... 5 seg ...)
finalizado...
Perplexed by this example, I ran to analyze the generated bytecode (naively) in search of the invokedynamic instruction and what I got was:
// class version 52.0 (52)
// access flags 0x21
public class NashornEval {
// compiled from: NashornEval.java
// access flags 0x1
public <init>() : void
L0
LINENUMBER 7 L0
ALOAD 0: this
INVOKESPECIAL Object.<init> () : void
RETURN
L1
LOCALVARIABLE this NashornEval L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x89
public static transient varargs main(String[]) : void
TRYCATCHBLOCK L0 L1 L2 ScriptException
L3
LINENUMBER 10 L3
NEW ScriptEngineManager
DUP
INVOKESPECIAL ScriptEngineManager.<init> () : void
ASTORE 1
L4
LINENUMBER 11 L4
ALOAD 1: manager
LDC "nashorn"
INVOKEVIRTUAL ScriptEngineManager.getEngineByName (String) : ScriptEngine
ASTORE 2
L5
LINENUMBER 14 L5
LDC "var Thread = java.lang.Thread; \n"
ASTORE 3
L6
LINENUMBER 15 L6
NEW StringBuilder
DUP
ALOAD 3: js
INVOKESTATIC String.valueOf (Object) : String
INVOKESPECIAL StringBuilder.<init> (String) : void
LDC "var map = Array.prototype.map \n"
INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString () : String
ASTORE 3: js
L7
LINENUMBER 16 L7
NEW StringBuilder
DUP
ALOAD 3: js
INVOKESTATIC String.valueOf (Object) : String
INVOKESPECIAL StringBuilder.<init> (String) : void
LDC "var names = [\"corinthians\", \"palmeiras\", \"santos\"]\n"
INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString () : String
ASTORE 3: js
L8
LINENUMBER 17 L8
NEW StringBuilder
DUP
ALOAD 3: js
INVOKESTATIC String.valueOf (Object) : String
INVOKESPECIAL StringBuilder.<init> (String) : void
LDC "var a = map.call(names, function(name) { return name.length() })\n"
INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString () : String
ASTORE 3: js
L9
LINENUMBER 18 L9
NEW StringBuilder
DUP
ALOAD 3: js
INVOKESTATIC String.valueOf (Object) : String
INVOKESPECIAL StringBuilder.<init> (String) : void
LDC "print(a); \n"
INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString () : String
ASTORE 3: js
L10
LINENUMBER 19 L10
NEW StringBuilder
DUP
ALOAD 3: js
INVOKESTATIC String.valueOf (Object) : String
INVOKESPECIAL StringBuilder.<init> (String) : void
LDC "Thread.sleep(5000); \n"
INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString () : String
ASTORE 3: js
L11
LINENUMBER 20 L11
NEW StringBuilder
DUP
ALOAD 3: js
INVOKESTATIC String.valueOf (Object) : String
INVOKESPECIAL StringBuilder.<init> (String) : void
LDC "print(\"finalizado...\");"
INVOKEVIRTUAL StringBuilder.append (String) : StringBuilder
INVOKEVIRTUAL StringBuilder.toString () : String
ASTORE 3: js
L0
LINENUMBER 23 L0
ALOAD 2: engine
ALOAD 3: js
INVOKEINTERFACE ScriptEngine.eval (String) : Object
POP
L1
LINENUMBER 24 L1
GOTO L12
L2
FRAME FULL [String[] ScriptEngineManager ScriptEngine String] [ScriptException]
ASTORE 4
L13
LINENUMBER 25 L13
ALOAD 4: e
INVOKEVIRTUAL ScriptException.printStackTrace () : void
L12
LINENUMBER 28 L12
FRAME SAME
RETURN
L14
LOCALVARIABLE args String[] L3 L14 0
LOCALVARIABLE manager ScriptEngineManager L4 L14 1
LOCALVARIABLE engine ScriptEngine L5 L14 2
LOCALVARIABLE js String L6 L14 3
LOCALVARIABLE e ScriptException L13 L12 4
MAXSTACK = 3
MAXLOCALS = 5
}
Soon I was sure the routine that is responsible for the execution of "non-typed language" (Nashorn) o should do so at execution time.
My next step would be to identify it, and where I could get closer was by displaying a process histogram at runtime from the jvm instance responsible for running my Nashorneval example. So I did:
$ jps
40231 Jps
40076 NashornEval
//PID da instancia jvm NashornEval = 40076
And using the jmap:
$ jmap -histo 40076 | grep dynamic
// -histo imprime o histograma do java object heap
// usei o grep pra restringir meu retorno a um match “dynamic”
And my return was:
6: 10265 410600 java.lang.invoke.MethodType
8: 10373 331936 java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry
12: 4395 246120 java.lang.invoke.MemberName
14: 2078 116368 java.lang.invoke.LambdaFormEditor$Transform
16: 2199 70368 java.lang.invoke.LambdaForm$Name
18: 1280 57864 [Ljava.lang.invoke.LambdaForm$Name;
20: 1622 51904 java.lang.invoke.BoundMethodHandle$Species_LL
21: 1454 46528 java.lang.invoke.DirectMethodHandle
22: 1384 44288 java.lang.invoke.BoundMethodHandle$Species_L
38: 1882 30112 java.lang.invoke.LambdaFormEditor
40: 602 28896 java.lang.invoke.LambdaForm
46: 396 22176 java.lang.invoke.MethodTypeForm
50: 865 20760 java.lang.invoke.MethodHandles$Lookup
51: 606 20720 [Ljava.lang.invoke.MethodHandle;
57: 238 15232 java.lang.invoke.InvokerBytecodeGenerator
60: 577 13848 java.lang.invoke.LambdaForm$NamedFunction
63: 279 13136 [Ljava.lang.invoke.LambdaForm$BasicType;
74: 211 8440 java.lang.invoke.BoundMethodHandle$Species_L3
94: 99 4752 java.lang.invoke.LambdaFormBuffer
101: 126 4032 java.lang.invoke.BoundMethodHandle$Species_LI
106: 90 3600 java.lang.invoke.BoundMethodHandle$Species_L3I
111: 62 2976 java.lang.invoke.MethodHandleImpl$CountingWrapper
114: 66 2640 java.lang.invoke.DirectMethodHandle$Accessor
118: 61 2440 java.lang.invoke.MethodHandleImpl$AsVarargsCollector
119: 60 2400 java.lang.invoke.BoundMethodHandle$Species_LILL
124: 40 1920 java.lang.invoke.BoundMethodHandle$Species_LIL3
130: 45 1800 java.lang.invoke.BoundMethodHandle$Species_LIL
133: 69 1656 java.lang.invoke.Invokers
152: 33 1200 [Ljava.lang.invoke.LambdaFormEditor$Transform;
171: 20 800 java.lang.invoke.BoundMethodHandle$SpeciesData
172: 25 800 java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle
179: 18 720 [Ljava.lang.invoke.BoundMethodHandle$SpeciesData;
180: 18 720 java.lang.invoke.BoundMethodHandle$Species_LLI
191: 27 648 java.lang.invoke.SimpleMethodHandle
192: 40 640 java.lang.invoke.MutableCallSite
194: 3 624 [Ljava.lang.invoke.LambdaForm;
202: 19 600 [Ljava.lang.invoke.LambdaForm$NamedFunction;
204: 9 576 [Lsun.invoke.util.Wrapper;
209: 10 560 sun.invoke.util.Wrapper
210: 23 552 [Ljava.lang.invoke.MutableCallSite;
211: 23 552 [Ljava.lang.invoke.SwitchPoint;
224: 11 440 java.lang.invoke.MethodHandleImpl$WrappedMember
231: 10 400 java.lang.invoke.BoundMethodHandle$Species_LLIL
255: 14 336 java.lang.invoke.LambdaFormEditor$Transform$Kind
263: 10 320 java.lang.invoke.DirectMethodHandle$Special
281: 17 272 sun.invoke.util.ValueConversions$WrapperCache
282: 11 264 java.lang.invoke.SwitchPoint
305: 5 200 java.lang.invoke.BoundMethodHandle$Species_L4
308: 4 192 java.lang.invoke.BoundMethodHandle$Species_L5
309: 6 192 java.lang.invoke.InvokerBytecodeGenerator$CpPatch
310: 6 192 java.lang.invoke.LambdaForm$BasicType
311: 8 192 java.lang.invoke.MethodHandleImpl$Intrinsic
341: 4 136 [Lsun.invoke.util.ValueConversions$WrapperCache;
377: 1 96 [Ljava.lang.invoke.MethodType;
379: 2 96 java.lang.invoke.BoundMethodHandle$Species_L3IL
418: 1 72 [Ljava.lang.invoke.LambdaFormEditor$Transform$Kind;
449: 2 64 java.lang.invoke.BoundMethodHandle$Species_D
523: 1 48 [Ljava.lang.invoke.MethodHandleImpl$Intrinsic;
532: 1 48 java.lang.invoke.BoundMethodHandle$Species_LLILL
588: 1 40 [[Ljava.lang.invoke.LambdaForm$Name;
633: 1 32 java.lang.invoke.BoundMethodHandle$Species_I
679: 1 24 java.lang.invoke.DirectMethodHandle$EnsureInitialized
680: 1 24 java.lang.invoke.MethodHandleImpl$4
681: 1 24 java.lang.invoke.MethodHandleImpl$ArrayAccessor$1
682: 1 24 java.lang.invoke.MethodType$ConcurrentWeakInternSet
753: 1 16 java.lang.invoke.MemberName$Factory
754: 1 16 java.lang.invoke.MethodHandleImpl$2
755: 1 16 java.lang.invoke.MethodHandleImpl$3
And there it was, the engine nashorn doing the magic:
192: 40 640 java.lang.invoke.MutableCallSite
Mutablecallsite is a Callsite whose target variable behaves as
a common field. An invokedynamic statement is linked to
Mutablecallsite delegating all calls to the site’s current target.
The dynamic summoner of a callsite mutable also delegates each
call to originating target.
I’m still very interested in more complex applications using Ducktyping, but I was pleased for the moment, I hope it helps to clarify the subject for others too.
Related: http://answall.com/q/71340/132
– Victor Stafusa