2015-06-16 12 views
6


Próbuję mieć Java 8 Nashorn z kompletnym źródłem (bez oprzyrządowania). Jak być może wiesz, używa on Nasgen do modyfikacji klas., A dane wyjściowe są wysyłane w JRE/lib/ext/nashorn.jar.Kod Java do kompilacji w MethodHandle w stałej puli


Na demontażu wyjścia, używając 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 

które mogłyby być błędnie napisany jako

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

, który powinien wywołać super konstruktora z podpisem:

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



Mój problem jest drugim parametrem NativeFunction.function, które nie mogą mieć compilable źródła, do wytworzenia tej samej MethodHandle w stałej puli,

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

Ta część instrumentarium zostało zrobione przez ASM, dzwoniąc pod numer MethodVisitor.visitLdcInsn.

Czy istnieje sposób skonstruowania takiego uchwytu metody ze źródła Java, czy jest to funkcja, która może być wykonana tylko na poziomie kodu bajtowego?

Pełne wyjście 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

To prawdopodobnie tylko kod bajtowy. Jest wiele rzeczy, których inne języki JVM nie mogą zrobić w Javie, a to kwestia specyfikacji języka, a nie kodów bajtowych. z. – markspace

+2

Jedyną funkcją języka Java, o której wiem, która używa opcode 'invokespecial' jest lambdas. Poza tym jest używany głównie do dynamicznych języków (takich jak Javascript) działających na maszynie JVM. Nie wiem, czy to pomaga. – biziclop

+0

To miało być oczywiście "invokedynamic". – biziclop

Odpowiedz

6

Nie ma konstrukt język Java, aby produkować instrukcja ldc ładowania MethodHandle. Mimo to, można stworzyć równoważne uchwyt o bardziej skomplikowanej konstrukcji:

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

Nie tylko jest to bardziej skomplikowane niż jednej instrukcji ldc kodu bajtowego, to są również zmuszeni do czynienia z zaznaczonych wyjątków NoSuchMethodException i IllegalAccessException (lub ich wspólny przodek ReflectiveOperationException).

można upakować działanie w sposób podobny

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

i nazywają to w sobie konstruktora jako

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

zaletą tego podejścia jest to, że można użyć Indify przekonwertować inwokację MH_NativeFunction_function() z powrotem do instrukcji ldc ładowanie MethodHandle ze stałej puli.

Powiązane problemy