2015-06-16 9 views
6


Я пытаюсь создать Java 8 Nashorn с полным исходным кодом (без инструментов). Как вы знаете, он использует Nasgen для модификации .classes, а выход отправляется в JRE/lib/ext/nashorn.jar.Код Java для компиляции в MethodHandle в Constant Pool


На разборке выход, используя 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 

, которые могут быть ошибочно написана как

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

, которая должна вызвать супер конструктор с подписью:

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



Мой вопрос является второй параметр NativeFunction.function, который я не мог иметь компилируемый источник, чтобы генерировать в постоянном пуле тот же MethodHandle,

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

Та часть аппаратуры была сделана ASM, по телефону MethodVisitor.visitLdcInsn.

Итак, есть ли способ создать такой дескриптор метода из источника Java, или это функция, которая может быть выполнена только на уровне байт-кода?

Полный выход javap:

$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

Скорее всего, код байта. Есть несколько вещей, которые другие языки JVM делают, что Java не может, и это вопрос спецификации языка, а не то, что могут использоваться в байтовых кодах. из. – markspace

+2

Единственная функция языка Java, о которой я знаю, использует код операции 'invokespecial' - lambdas. Помимо этого, он в основном используется для динамических языков (например, Javascript), работающих на JVM. Я не знаю, поможет ли это. – biziclop

+0

Это должно было быть 'invokedynamic', конечно. – biziclop

ответ

6

Там нет языка Java конструкт для получения ldc инструкции загрузки MethodHandle. Тем не менее, вы можете создать эквивалентную ручки с более сложной конструкцией:

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

это не только более сложным, чем одной инструкции ldc байт-кода, вы также вынуждены иметь дело с проверенными исключениями NoSuchMethodException и IllegalAccessException (или их общий предок ReflectiveOperationException).

Вы можете инкапсулировать операцию в метод как

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); 
    } 
} 

и назвать его в вас конструктору

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

преимущество этого подхода заключается в том, что вы можете использовать Indify преобразовать вызов MH_NativeFunction_function() вернуться к инструкции ldc, загрузив MethodHandle из постоянного пула.