2015-06-16 8 views
6


Ich versuche, Java 8 Nashorn mit vollständiger Quelle (nicht instrumentiert) zu haben. Wie Sie vielleicht wissen, verwendet es Nasgen die .classes zu ändern und die Ausgabe in JRE/lib/ext/nashorn.jar ausgeliefert wird.Java-Code, der in MethodHandle im konstanten Pool kompiliert wird


auf den Ausgang der Demontage mit javap:

0: aload_0 
1: ldc   #24     // String Function 
3: ldc   #31     // MethodHandle invokestatic jdk/nashorn/internal/objects/NativeFunction.function:(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 
5: getstatic  #22     // Field $nasgenmap$:Ljdk/nashorn/internal/runtime/PropertyMap; 
8: aconst_null 
9: invokespecial #34     // Method jdk/nashorn/internal/objects/ScriptFunctionImpl."<init>":(Ljava/lang/String;Ljava/lang/invoke/MethodHandle;Ljdk/nashorn/internal/runtime/PropertyMap;[Ljdk/nashorn/internal/runtime/Specialization;)V 

, die sein könnte fälschlicherweise als

geschrieben
super("Function", NativeFunction.function, $nasgenmap$, (Specialization[]) null); 

, die den Super-Konstruktor mit Unterschrift nennen sollte:

ScriptFunctionImpl(String, MethodHandle, PropertyMap, Specialization[]) { } 



Mein Problem ist der zweite Parameter NativeFunction.function, die ich nicht übersetzbar Quelle haben könnte, die gleichen MethodHandle im Konstanten-Pool zu erzeugen,

#31 = MethodHandle  #6:#30   // invokestatic jdk/nashorn/internal/objects/NativeFunction.function:(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 

Dieser Teil der Instrumentierung von ASM getan wurde, durch den Anruf .

So ist es eine Möglichkeit, ein solches Verfahren Griff aus der Java-Quellcode zu erstellen, oder das ist ein Merkmal, das nur auf Bytecode-Ebene getan werden kann?

Der vollständige javap Ausgang:

$javap -c -v NativeFunction$Constructor.class 

    Last modified Apr 10, 2015; size 1161 bytes 
    MD5 checksum dcae2f54643befc519a45e9ac9bc4781 
final class jdk.nashorn.internal.objects.NativeFunction$Constructor extends jdk.nashorn.internal.objects.ScriptFunctionImpl 
    minor version: 0 
    major version: 51 
    flags: ACC_FINAL 
Constant pool: 
    #1 = Utf8    jdk/nashorn/internal/objects/NativeFunction$Constructor 
    #2 = Class    #1    // jdk/nashorn/internal/objects/NativeFunction$Constructor 
    #3 = Utf8    jdk/nashorn/internal/objects/ScriptFunctionImpl 
    #4 = Class    #3    // jdk/nashorn/internal/objects/ScriptFunctionImpl 
    #5 = Utf8    $nasgenmap$ 
    #6 = Utf8    Ljdk/nashorn/internal/runtime/PropertyMap; 
    #7 = Utf8    <clinit> 
    #8 = Utf8    ()V 
    #9 = Utf8    java/util/ArrayList 
    #10 = Class    #9    // java/util/ArrayList 
    #11 = Utf8    <init> 
    #12 = Utf8    (I)V 
    #13 = NameAndType  #11:#12  // "<init>":(I)V 
    #14 = Methodref   #10.#13  // java/util/ArrayList."<init>":(I)V 
    #15 = Utf8    jdk/nashorn/internal/runtime/PropertyMap 
    #16 = Class    #15   // jdk/nashorn/internal/runtime/PropertyMap 
    #17 = Utf8    newMap 
    #18 = Utf8    (Ljava/util/Collection;)Ljdk/nashorn/internal/runtime/PropertyMap; 
    #19 = NameAndType  #17:#18  // newMap:(Ljava/util/Collection;)Ljdk/nashorn/internal/runtime/PropertyMap; 
    #20 = Methodref   #16.#19  // jdk/nashorn/internal/runtime/PropertyMap.newMap:(Ljava/util/Collection;)Ljdk/nashorn/internal/runtime/PropertyMap; 
    #21 = NameAndType  #5:#6   // $nasgenmap$:Ljdk/nashorn/internal/runtime/PropertyMap; 
    #22 = Fieldref   #2.#21   // jdk/nashorn/internal/objects/NativeFunction$Constructor.$nasgenmap$:Ljdk/nashorn/internal/runtime/PropertyMap; 
    #23 = Utf8    Function 
    #24 = String    #23   // Function 
    #25 = Utf8    jdk/nashorn/internal/objects/NativeFunction 
    #26 = Class    #25   // jdk/nashorn/internal/objects/NativeFunction 
    #27 = Utf8    function 
    #28 = Utf8    (ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 
    #29 = NameAndType  #27:#28  // function:(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 
    #30 = Methodref   #26.#29  // jdk/nashorn/internal/objects/NativeFunction.function:(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 
    #31 = MethodHandle  #6:#30   // invokestatic jdk/nashorn/internal/objects/NativeFunction.function:(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 
    #32 = Utf8    (Ljava/lang/String;Ljava/lang/invoke/MethodHandle;Ljdk/nashorn/internal/runtime/PropertyMap;[Ljdk/nashorn/internal/runtime/Specialization;)V 
    #33 = NameAndType  #11:#32  // "<init>":(Ljava/lang/String;Ljava/lang/invoke/MethodHandle;Ljdk/nashorn/internal/runtime/PropertyMap;[Ljdk/nashorn/internal/runtime/Specialization;)V 
    #34 = Methodref   #4.#33   // jdk/nashorn/internal/objects/ScriptFunctionImpl."<init>":(Ljava/lang/String;Ljava/lang/invoke/MethodHandle;Ljdk/nashorn/internal/runtime/PropertyMap;[Ljdk/nashorn/internal/runtime/Specialization;)V 
    #35 = Utf8    jdk/nashorn/internal/objects/NativeFunction$Prototype 
    #36 = Class    #35   // jdk/nashorn/internal/objects/NativeFunction$Prototype 
    #37 = NameAndType  #11:#8   // "<init>":()V 
    #38 = Methodref   #36.#37  // jdk/nashorn/internal/objects/NativeFunction$Prototype."<init>":()V 
    #39 = Utf8    jdk/nashorn/internal/objects/PrototypeObject 
    #40 = Class    #39   // jdk/nashorn/internal/objects/PrototypeObject 
    #41 = Utf8    setConstructor 
    #42 = Utf8    (Ljava/lang/Object;Ljava/lang/Object;)V 
    #43 = NameAndType  #41:#42  // setConstructor:(Ljava/lang/Object;Ljava/lang/Object;)V 
    #44 = Methodref   #40.#43  // jdk/nashorn/internal/objects/PrototypeObject.setConstructor:(Ljava/lang/Object;Ljava/lang/Object;)V 
    #45 = Utf8    jdk/nashorn/internal/runtime/ScriptFunction 
    #46 = Class    #45   // jdk/nashorn/internal/runtime/ScriptFunction 
    #47 = Utf8    setPrototype 
    #48 = Utf8    (Ljava/lang/Object;)V 
    #49 = NameAndType  #47:#48  // setPrototype:(Ljava/lang/Object;)V 
    #50 = Methodref   #46.#49  // jdk/nashorn/internal/runtime/ScriptFunction.setPrototype:(Ljava/lang/Object;)V 
    #51 = Utf8    setArity 
    #52 = NameAndType  #51:#12  // setArity:(I)V 
    #53 = Methodref   #46.#52  // jdk/nashorn/internal/runtime/ScriptFunction.setArity:(I)V 
    #54 = Utf8    Code 
{ 
    public static {}; 
    flags: ACC_PUBLIC, ACC_STATIC 
    Code: 
     stack=3, locals=0, args_size=0 
     0: new   #10     // class java/util/ArrayList 
     3: dup 
     4: iconst_1 
     5: invokespecial #14     // Method java/util/ArrayList."<init>":(I)V 
     8: invokestatic #20     // Method jdk/nashorn/internal/runtime/PropertyMap.newMap:(Ljava/util/Collection;)Ljdk/nashorn 
/internal/runtime/PropertyMap; 
     11: putstatic  #22     // Field $nasgenmap$:Ljdk/nashorn/internal/runtime/PropertyMap; 
     14: return 

    jdk.nashorn.internal.objects.NativeFunction$Constructor(); 
    flags: 
    Code: 
     stack=5, locals=1, args_size=1 
     0: aload_0 
     1: ldc   #24     // String Function 
     3: ldc   #31     // MethodHandle invokestatic jdk/nashorn/internal/objects/NativeFunction.function:(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction; 
     5: getstatic  #22     // Field $nasgenmap$:Ljdk/nashorn/internal/runtime/PropertyMap; 
     8: aconst_null 
     9: invokespecial #34     // Method jdk/nashorn/internal/objects/ScriptFunctionImpl."<init>":(Ljava/lang/String;Ljava/lang/invoke/MethodHandle;Ljdk/nashorn/internal/runtime/PropertyMap;[Ljdk/nashorn/internal/runtime/Specialization;)V 
     12: aload_0 
     13: new   #36     // class jdk/nashorn/internal/objects/NativeFunction$Prototype 
     16: dup 
     17: invokespecial #38     // Method jdk/nashorn/internal/objects/NativeFunction$Prototype."<init>":()V 
     20: dup 
     21: aload_0 
     22: invokestatic #44     // Method jdk/nashorn/internal/objects/PrototypeObject.setConstructor:(Ljava/lang/Object;Ljava/lang/Object;)V 
     25: invokevirtual #50     // Method jdk/nashorn/internal/runtime/ScriptFunction.setPrototype:(Ljava/lang/Object;)V 
     28: aload_0 
     29: iconst_1 
     30: invokevirtual #53     // Method jdk/nashorn/internal/runtime/ScriptFunction.setArity:(I)V 
     33: return 
} 
+3

Es ist wahrscheinlich, Byte-Code. Es gibt mehrere Dinge, die anderen JVM Sprachen zu tun, dass Java nicht kann, und es ist eine Frage der Sprachspezifikation, nicht das, was die Byte-Codes sind in der Lage. von. – markspace

+2

Die einzige Java-Sprache-Funktion ich darüber wissen verwendet das 'invokespecial' Opcode lambda ist. Ansonsten wird es hauptsächlich für dynamische Sprachen (wie Javascript) verwendet, die auf der JVM laufen. Ich weiß nicht, ob das hilft. – biziclop

+0

Das sollte natürlich "aufgerufen" werden. – biziclop

Antwort

6

Es gibt kein Java-Sprachkonstrukt eine ldc Anweisung Laden ein MethodHandle zu erzeugen.

MethodHandles.lookup().findStatic(
    jdk.nashorn.internal.objects.NativeFunction.class, "function", 
    MethodType.fromMethodDescriptorString(
    "(ZLjava/lang/Object;[Ljava/lang/Object;)Ljdk/nashorn/internal/runtime/ScriptFunction;", 
    null)) 

Dies ist nicht nur komplizierter als eine einzelne ldc Bytecode-Anweisung, die Sie auch befassen sich mit den geprüften Ausnahmen NoSuchMethodException gezwungen und IllegalAccessException (: Still, können Sie einen äquivalent Griff mit einem komplizierteren konstrukt oder ihr gemeinsamer Vorfahr ReflectiveOperationException).

Sie den Betrieb in einem Verfahren wie

private static MethodHandle MH_NativeFunction_function() { 
    try { 
    return MethodHandles.lookup().findStatic(
     jdk.nashorn.internal.objects.NativeFunction.class, "function", 
     MethodType.fromMethodDescriptorString("(ZLjava/lang/Object;[Ljava/lang/Object;)" 
     + "Ljdk/nashorn/internal/runtime/ScriptFunction;", null)); 
    } catch(ReflectiveOperationException ex) { 
     throw new AssertionError(ex); 
    } 
} 

und nennen Sie es in Ihnen Konstruktor einkapseln kann als

super("Function", MH_NativeFunction_function(), $nasgenmap$, (Specialization[]) null); 

der Vorteil dieses Ansatzes ist, dass Sie Indify den Aufruf konvertieren können MH_NativeFunction_function() zurück zu einem ldc Befehl die MethodHandle von dem konstanten Pool laden. nur