2015-06-16 17 views
6


Tôi đang cố gắng để có Java 8 Nashorn với nguồn hoàn chỉnh (không được thiết bị). Như bạn có thể biết, nó sử dụng Nasgen để sửa đổi các lớp., Và đầu ra được vận chuyển trong JRE/lib/ext/nashorn.jar.Mã Java sẽ được biên dịch vào MethodHandle trong Hồ bơi không đổi


On tháo đầu ra, sử dụng 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 

mà có thể là sai lầm viết như

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

, mà nên gọi các nhà xây dựng siêu với chữ ký:

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



Vấn đề của tôi là tham số thứ hai NativeFunction.function, mà tôi không thể có một nguồn biên dịch được, để tạo ra các giống MethodHandle trong hồ bơi thường xuyên,

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

Đó là một phần của thiết bị đo đạc được thực hiện bởi ASM, bằng cách gọi số MethodVisitor.visitLdcInsn.

Vì vậy, có cách nào để xây dựng một phương thức xử lý như vậy từ nguồn Java hay đây là một tính năng chỉ có thể được thực hiện ở cấp độ bytecode?

Sản lượng javap đầy đủ:

$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

Chỉ có khả năng là mã byte. Có một số thứ mà các ngôn ngữ JVM khác làm cho Java không thể, và nó là vấn đề của đặc tả ngôn ngữ, không phải là những gì các mã byte có khả năng. của. – markspace

+2

Tính năng ngôn ngữ Java duy nhất tôi biết về việc sử dụng opcode 'invokespecial' là lambdas. Khác hơn là nó chủ yếu được sử dụng cho các ngôn ngữ động (như Javascript) chạy trên JVM. Tôi không biết liệu điều này có giúp ích gì không. – biziclop

+0

Điều đó có nghĩa là 'động lực học' dĩ nhiên. – biziclop

Trả lời

6

Không có cấu trúc ngôn ngữ Java để tạo ra một hướng dẫn ldc tải một MethodHandle. Tuy nhiên, bạn có thể tạo một tương đương xử lý với một cấu trúc phức tạp hơn:

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

Không chỉ là này phức tạp hơn một hướng dẫn ldc bytecode duy nhất, bạn cũng buộc phải đối phó với những trường hợp ngoại lệ kiểm tra NoSuchMethodExceptionIllegalAccessException (hoặc tổ tiên chung của chúng ReflectiveOperationException).

Bạn có thể tóm lược hoạt động vào một phương pháp như

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

và gọi nó là ở bạn constructor như

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

lợi thế của phương pháp này là bạn có thể sử dụng Indify để chuyển đổi gọi MH_NativeFunction_function() quay lại hướng dẫn ldc tải MethodHandle từ hồ bơi không đổi.

Các vấn đề liên quan