2017-12-11 31 views
5

के साथ प्रतिस्थापित की गई है I उच्च प्रदर्शन कोड में इन साधारण लैम्ब्डा इंटरफेस का उपयोग कर रहा हूं।सरल लैम्ब्डा संरचना इनलाइन कोड

@FunctionalInterface 
public interface Block<T> { 
    T apply() throws Exception; 
} 

@FunctionalInterface 
public interface Block1 { 
    void apply() throws Exception; 
} 

final void func1(final Block1 b){ my implementation ...}; 
final <T> func(final Block<T> b){ my implementation ...}; 

मैं पूछ रहा हूँ:

func(()->{ generic code inside }); 

या

Object ret=func(()->{ generic code ... return result }) 

तरह स्रोत कोड के लिए JDK बाइट कोड इनलाइन ब्लॉक साथ बदल दिया है?

+0

अफैइक, कोड गैर-रेखांकित बाइटकोड, एक कक्षा प्रति लैम्ब्डा के लिए संकलित करता है। हालांकि, जेवीएम जेआईटी संकलन के दौरान रनटाइम में रेखांकित कर सकता है, जो अक्सर करता है, खासकर भारी इस्तेमाल किए गए कोड में। – xs0

+0

क्या आपने बनाए गए बाइट कोड का निरीक्षण करने की कोशिश की है? आप इसे [javap] (https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javap.html) – devpuh

+0

से थोड़ा भ्रामक कर सकते हैं ... क्या आपका मतलब है 'इनलाइन' (जैसा कि एक विधि में दूसरे में रेखांकित हो जाता है?) क्योंकि आपके प्रश्न से ऐसा लगता है कि आप पूछ रहे हैं कि लैम्ब्डा का एक उदाहरण कैश हो जाता है या नहीं। तो यह कौनसा है? – Eugene

उत्तर

1

नहीं, लैम्ब्डा बाइट कोड में इनलाइन ब्लॉक नहीं बनाता है।

Java Language Specification: 15.27.4. Run-Time Evaluation of Lambda Expressions

देखें रन समय, एक लैम्ब्डा अभिव्यक्ति के मूल्यांकन के रूप में सामान्य insofar के पूरा होने के एक वस्तु के लिए एक संदर्भ पैदा करता है, एक वर्ग उदाहरण निर्माण अभिव्यक्ति की मूल्यांकन के समान है। लैम्ब्डा अभिव्यक्ति का मूल्यांकन लैम्ब्डा शरीर के निष्पादन से अलग है।


यहाँ एक सरल परीक्षण कार्यक्रम क्या बाइट कोड बनाई गई है देखने के लिए है। इसके लिए हमारे पास एक इंटरफेस और एक साधारण मुख्य वर्ग है।

Block.java

@FunctionalInterface 
public interface Block<T> { 
    T apply() throws Exception; 
} 

Main.java

public class Main { 
    public static void main(String[] args) throws Exception { 
     String foobar = func(() -> "Hello World"); 
     System.out.println(foobar); 
    } 

    final static <T> T func(final Block<T> b) throws Exception { 
     return b.apply(); 
    } 
} 

यह संकलित करें, अब आप बाईटकोड देखने पर javap उपयोग कर सकते हैं:

javap -verbose Block.class प्रिंट:

Classfile Block.class 
    Last modified 11.12.2017; size 331 bytes 
    MD5 checksum d6e4627f60a7cb24b7f23064c156ede6 
    Compiled from "Block.java" 
public interface Block<T extends java.lang.Object> 
    minor version: 0 
    major version: 52 
    flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT 
Constant pool: 
    #1 = Class    #2    // Block 
    #2 = Utf8    Block 
    #3 = Class    #4    // java/lang/Object 
    #4 = Utf8    java/lang/Object 
    #5 = Utf8    apply 
    #6 = Utf8    ()Ljava/lang/Object; 
    #7 = Utf8    Exceptions 
    #8 = Class    #9    // java/lang/Exception 
    #9 = Utf8    java/lang/Exception 
    #10 = Utf8    Signature 
    #11 = Utf8    ()TT; 
    #12 = Utf8    SourceFile 
    #13 = Utf8    Block.java 
    #14 = Utf8    <T:Ljava/lang/Object;>Ljava/lang/Object; 
    #15 = Utf8    RuntimeVisibleAnnotations 
    #16 = Utf8    Ljava/lang/FunctionalInterface; 
{ 
    public abstract T apply() throws java.lang.Exception; 
    descriptor:()Ljava/lang/Object; 
    flags: ACC_PUBLIC, ACC_ABSTRACT 
    Exceptions: 
     throws java.lang.Exception 
    Signature: #11       //()TT; 
} 
SourceFile: "Block.java" 
Signature: #14       // <T:Ljava/lang/Object;>Ljava/lang/Object; 
RuntimeVisibleAnnotations: 
    0: #16() 

javap -verbose Main.class प्रिंट:

Classfile Main.class 
    Last modified 11.12.2017; size 1512 bytes 
    MD5 checksum 73ceb403dfcecbf4dbb5e03ec2fe852d 
    Compiled from "Main.java" 
public class Main 
    minor version: 0 
    major version: 52 
    flags: ACC_PUBLIC, ACC_SUPER 
Constant pool: 
    #1 = Class    #2    // Main 
    #2 = Utf8    Main 
    #3 = Class    #4    // java/lang/Object 
    #4 = Utf8    java/lang/Object 
    #5 = Utf8    <init> 
    #6 = Utf8    ()V 
    #7 = Utf8    Code 
    #8 = Methodref   #3.#9   // java/lang/Object."<init>":()V 
    #9 = NameAndType  #5:#6   // "<init>":()V 
    #10 = Utf8    LineNumberTable 
    #11 = Utf8    LocalVariableTable 
    #12 = Utf8    this 
    #13 = Utf8    LMain; 
    #14 = Utf8    main 
    #15 = Utf8    ([Ljava/lang/String;)V 
    #16 = Utf8    Exceptions 
    #17 = Class    #18   // java/lang/Exception 
    #18 = Utf8    java/lang/Exception 
    #19 = NameAndType  #20:#21  // apply:()LBlock; 
    #20 = Utf8    apply 
    #21 = Utf8    ()LBlock; 
    #22 = InvokeDynamic  #0:#19   // #0:apply:()LBlock; 
    #23 = Methodref   #1.#24   // Main.func:(LBlock;)Ljava/lang/Object; 
    #24 = NameAndType  #25:#26  // func:(LBlock;)Ljava/lang/Object; 
    #25 = Utf8    func 
    #26 = Utf8    (LBlock;)Ljava/lang/Object; 
    #27 = Class    #28   // java/lang/String 
    #28 = Utf8    java/lang/String 
    #29 = Fieldref   #30.#32  // java/lang/System.out:Ljava/io/PrintStream; 
    #30 = Class    #31   // java/lang/System 
    #31 = Utf8    java/lang/System 
    #32 = NameAndType  #33:#34  // out:Ljava/io/PrintStream; 
    #33 = Utf8    out 
    #34 = Utf8    Ljava/io/PrintStream; 
    #35 = Methodref   #36.#38  // java/io/PrintStream.println:(Ljava/lang/String;)V 
    #36 = Class    #37   // java/io/PrintStream 
    #37 = Utf8    java/io/PrintStream 
    #38 = NameAndType  #39:#40  // println:(Ljava/lang/String;)V 
    #39 = Utf8    println 
    #40 = Utf8    (Ljava/lang/String;)V 
    #41 = Utf8    args 
    #42 = Utf8    [Ljava/lang/String; 
    #43 = Utf8    foobar 
    #44 = Utf8    Ljava/lang/String; 
    #45 = Utf8    Signature 
    #46 = Utf8    <T:Ljava/lang/Object;>(LBlock<TT;>;)TT; 
    #47 = InterfaceMethodref #48.#50  // Block.apply:()Ljava/lang/Object; 
    #48 = Class    #49   // Block 
    #49 = Utf8    Block 
    #50 = NameAndType  #20:#51  // apply:()Ljava/lang/Object; 
    #51 = Utf8    ()Ljava/lang/Object; 
    #52 = Utf8    b 
    #53 = Utf8    LBlock; 
    #54 = Utf8    LocalVariableTypeTable 
    #55 = Utf8    LBlock<TT;>; 
    #56 = Utf8    lambda$0 
    #57 = Utf8    ()Ljava/lang/String; 
    #58 = String    #59   // Hello World 
    #59 = Utf8    Hello World 
    #60 = Utf8    SourceFile 
    #61 = Utf8    Main.java 
    #62 = Utf8    BootstrapMethods 
    #63 = Methodref   #64.#66  // java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #64 = Class    #65   // java/lang/invoke/LambdaMetafactory 
    #65 = Utf8    java/lang/invoke/LambdaMetafactory 
    #66 = NameAndType  #67:#68  // metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #67 = Utf8    metafactory 
    #68 = Utf8    (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #69 = MethodHandle  #6:#63   // invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #70 = MethodType   #51   // ()Ljava/lang/Object; 
    #71 = Methodref   #1.#72   // Main.lambda$0:()Ljava/lang/String; 
    #72 = NameAndType  #56:#57  // lambda$0:()Ljava/lang/String; 
    #73 = MethodHandle  #6:#71   // invokestatic Main.lambda$0:()Ljava/lang/String; 
    #74 = MethodType   #57   // ()Ljava/lang/String; 
    #75 = Utf8    InnerClasses 
    #76 = Class    #77   // java/lang/invoke/MethodHandles$Lookup 
    #77 = Utf8    java/lang/invoke/MethodHandles$Lookup 
    #78 = Class    #79   // java/lang/invoke/MethodHandles 
    #79 = Utf8    java/lang/invoke/MethodHandles 
    #80 = Utf8    Lookup 
{ 
    public Main(); 
    descriptor:()V 
    flags: ACC_PUBLIC 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0 
     1: invokespecial #8     // Method java/lang/Object."<init>":()V 
     4: return 
     LineNumberTable: 
     line 2: 0 
     LocalVariableTable: 
     Start Length Slot Name Signature 
      0  5  0 this LMain; 

    public static void main(java.lang.String[]) throws java.lang.Exception; 
    descriptor: ([Ljava/lang/String;)V 
    flags: ACC_PUBLIC, ACC_STATIC 
    Exceptions: 
     throws java.lang.Exception 
    Code: 
     stack=2, locals=2, args_size=1 
     0: invokedynamiC#22, 0    // InvokeDynamiC#0:apply:()LBlock; 
     5: invokestatic #23     // Method func:(LBlock;)Ljava/lang/Object; 
     8: checkcast  #27     // class java/lang/String 
     11: astore_1 
     12: getstatic  #29     // Field java/lang/System.out:Ljava/io/PrintStream; 
     15: aload_1 
     16: invokevirtual #35     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     19: return 
     LineNumberTable: 
     line 4: 0 
     line 5: 12 
     line 6: 19 
     LocalVariableTable: 
     Start Length Slot Name Signature 
      0  20  0 args [Ljava/lang/String; 
      12  8  1 foobar Ljava/lang/String; 

    static final <T extends java.lang.Object> T func(Block<T>) throws java.lang.Exception; 
    descriptor: (LBlock;)Ljava/lang/Object; 
    flags: ACC_STATIC, ACC_FINAL 
    Exceptions: 
     throws java.lang.Exception 
    Signature: #46       // <T:Ljava/lang/Object;>(LBlock<TT;>;)TT; 
    Code: 
     stack=1, locals=1, args_size=1 
     0: aload_0 
     1: invokeinterface #47, 1   // InterfaceMethod Block.apply:()Ljava/lang/Object; 
     6: areturn 
     LineNumberTable: 
     line 9: 0 
     LocalVariableTable: 
     Start Length Slot Name Signature 
      0  7  0  b LBlock; 
     LocalVariableTypeTable: 
     Start Length Slot Name Signature 
      0  7  0  b LBlock<TT;>; 
} 
SourceFile: "Main.java" 
BootstrapMethods: 
    0: #69 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    Method arguments: 
     #70()Ljava/lang/Object; 
     #73 invokestatic Main.lambda$0:()Ljava/lang/String; 
     #74()Ljava/lang/String; 
InnerClasses: 
    public static final #80= #76 of #78; //Lookup=class java/lang/invoke/MethodHandles$Lookup of class java/lang/invoke/MethodHandles 

आप देख सकते हैं लैम्ब्डा के लिए है कि यह एक

#73 invokestatic Main.lambda$0:()Ljava/lang/String; 

भी ब्लॉक के साथ

#22 = InvokeDynamic  #0:#19   // #0:apply:()LBlock; 
+0

आपके अध्ययन के लिए बहुत बहुत धन्यवाद ... यह अब बहुत स्पष्ट है –

2

Bytecode कहा जाता है (करीब) अप्रासंगिक जब विचार बनाता है जावा रनटाइम प्रदर्शन।

क्योंकि बस-इन-टाइम कंपाइलर रनटाइम पर किस प्रकार का मशीन कोड उत्पन्न करने का निर्णय लेता है।

यदि यह आपकी विधियों को लायक इनलाइनिंग के रूप में पाता है, तो ऐसा होगा - बाइटकोड कहता है इससे कोई फर्क नहीं पड़ता।

यदि यह पता चलता है कि आपकी विधियों को अक्सर JIT'ing के अधीन होने के लिए पर्याप्त नहीं कहा जाता है ... तो उनके कार्यान्वयन से कोई फर्क नहीं पड़ता।

इस संदर्भ में: अपने कोड की असली क्रम व्यवहार को समझने के लिए, आपको दो काम करने होते हैं: ए) JIT के कामकाज का अध्ययन (उदाहरण के लिए here देखें) और बी) क्रम की रूपरेखा । वास्तव में जानने के लिए, वास्तव में आपके डेटा और कोड के साथ आपकी कॉन्फ़िगरेशन में होता है।

और मामले में आप के बारे में कैसे lambdas सामान्य रूप में काम करते हैं पूछ रहे हैं: वे आम तौर पर invokedynamic बाईटकोड अनुदेश का उपयोग कर लागू कर रहे हैं (महिमा जानकारी के लिए here देखें)।

+0

जो * इनलाइनिंग * नहीं है * ओपी पूछ रहा है ... मुझे लगता है कि यह कैशिंग के बारे में अधिक है – Eugene

+0

इतना निश्चित नहीं है ... तदनुसार मेरा जवाब दोहराया। – GhostCat

+0

उन्हें 'invokedynamic' के माध्यम से नहीं बुलाया जाता है - आमंत्रण अभी भी एक सादा invokestatic या invokevirtual है। यह मुझे ओपी के उदाहरण 'ऑब्जेक्ट रेट = func (() -> {जेनेरिक कोड ... रिटर्न परिणाम} से लगता है)' कि वह कितने उदाहरण बनाए गए हैं और यदि यह * कैश किया गया है * – Eugene

संबंधित मुद्दे