Java 8 Lambda Implementation principle analysis

Source: Internet
Author: User

Reprint: http://blog.csdn.net/u012961566/article/details/78281654

To support functional programming, Java 8 introduces lambda expressions, so how do you implement lambda expressions in Java 8? After the lambda expression has been compiled, what exactly does it generate? Before we go into the analysis, let's consider that each lambda expression in Java 8 must have a functional interface corresponding to it, the difference between the functional interface and the ordinary interface, you can refer to the previous content, So you might be wondering if the lambda expression is transformed into an implementation class of the corresponding functional interface, and then the implementation of the subclass is called by polymorphic means, as the following code is a sample of a lambda expression

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} public class Lambda {public       static void Printstring (String s, print<string> Print) {        print.print (s);    } Public    static void Main (string[] args) {        printstring ("Test", (x), System.out.println (x));}    }

According to the above analysis, after the compiler has been processed in theory, the resulting code should be as follows:

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} Class Lambda$$0 implements print<string> {    @Override public    void Print (String x) {        SYSTEM.OUT.PRINTLN (x);    }} public class Lambda {public       static void Printstring (String s,             print<string> Print) {        print.print (s);    }    public static void Main (string[] args) {        printstring ("Test", New lambda$$0 ());}    }

or an inner class implementation, the code looks like this:

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} public class Lambda {       final class Lambda$$0 implements print<string> {        @Override public        void Print ( String x) {            System.out.println (x);        }    }      public static void Printstring (String s,             print<string> Print) {        print.print (s);    }     public static void Main (string[] args) {        printstring ("Test", New Lambda (). New lambda$$0 ());}    }

Or this anonymous inner class implementation, the code looks like this:

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} public class Lambda {public       static void Printstring (String s,             print<string> Print) {        print.print (s);    }    public static void Main (string[] args) {        printstring ("Test", new Print<string> () {            @Override            public void print (String x) {                System.out.println (x);            }}        );}    }

The code above, in addition to the code length of a point, with the implementation of the lambda expression code to run the result is the same, then how is Java 8 implemented in what way? is not one of the above three implementations, you may feel that you think is right, in fact, is right, in Java 8 is the use of internal classes to implement a lambda expression

So how is lambda expression implemented?

In order to explore how lambda expressions are implemented, it is necessary to study the bytecode files that are eventually converted into lambda tables, which requires a bytecode viewing tool and a counter-compilation tool in the Bin directory of the JDK

Javap-p Lambda.class

The-p in the above command indicates that all classes and members are output, and the result of running the above command is as follows:

Compiled from ' Lambda.java ' public class lambda {public  lambda ();  public static void Printstring (Java.lang.String, print<java.lang.string>);  public static void Main (java.lang.string[]);  private static void Lambda$0 (java.lang.String);}

As you can see from the code above, the compiler generates a private static function based on a lambda expression, noting that the build is what is said here, not the equivalent

private static void Lambda$0 (java.lang.String);

To verify that the above conversions are correct? We define a function in the code that lambda$0 this, and the final code looks like this:

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} public class Lambda {public       static void Printstring (String s,             print<string> Print) {        print.print (s);    }    private static void Lambda$0 (String s) {    } public    static void Main (string[] args) {        printstring ("Test", (x ), System.out.println (x));}    }

The above code will not error at compile time, but the runtime will error, because there are two lambda$0 functions, as shown below, is the runtime errors

 Exception in thread ' main ' Java.lang.ClassFormatError:Duplicate method Name&signature in class file Lambda at Java.lang.ClassLoader.defineClass1 (Native Method) at Java.lang.ClassLoader.defineClass (classloader.java:760) at JAV A.security.secureclassloader.defineclass (secureclassloader.java:142) at Java.net.URLClassLoader.defineClass ( urlclassloader.java:467) at java.net.urlclassloader.access$100 (urlclassloader.java:73) at java.net.URLClassLoader$ 1.run (urlclassloader.java:368) at Java.net.urlclassloader$1.run (urlclassloader.java:362) at Java.security.AccessController.doPrivileged (Native Method) at Java.net.URLClassLoader.findClass ( urlclassloader.java:361) at Java.lang.ClassLoader.loadClass (classloader.java:424) at sun.misc.launcher$ Appclassloader.loadclass (launcher.java:331) at Java.lang.ClassLoader.loadClass (classloader.java:357) at Sun.launcher.LauncherHelper.checkAndLoadMain (launcherhelper.java:495) 

The above error code is deserialized by JAVAP, and the members of the output class after the decompile are as follows

Compiled from ' Lambda.java ' public class lambda {public  lambda ();  public static void Printstring (Java.lang.String, print<java.lang.string>);  private static void Lambda$0 (java.lang.String);  public static void Main (java.lang.string[]);  private static void Lambda$0 (java.lang.String);}

Will find that lambda$0 appears two times, so when the code is running, it is not known which to call, so it will be thrown wrong.

With the above, it can be known that the lambda expression in Java 8 first generates a private static function, the private static function is the content of the lambda expression, so the above code can initially be converted to the code shown below

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} public class Lambda {public       static void Printstring (String s, print<string> Print) {        print.print (s);    }        private static void Lambda$0 (String x) {        System.out.println (x);    }        public static void Main (string[] args) {        printstring ("Test",/**lambda expression**/);}    }

After the conversion to the above form, then how to implement the call static Lambda$0 function, here can be a breakpoint in the following method, you can find in the lambda expression, the runtime will enter this function

public static CallSite metafactory (methodhandles.lookup caller,                                       String invokedname,                                       methodtype Invokedtype,                                       Methodtype Sammethodtype,                                       Methodhandle Implmethod,                                       methodtype instantiatedmethodtype)            throws lambdaconversionexception {        abstractvalidatinglambdametafactory MF;        MF = new Innerclasslambdametafactory (caller, Invokedtype,                                             invokedname, Sammethodtype,                                             Implmethod, Instantiatedmethodtype,                                             false, Empty_class_array, Empty_mt_array);        Mf.validatemetafactoryargs ();        return Mf.buildcallsite ();}

In this function, it can be found that an inner class was generated for the lambda expression, in order to verify that an inner class was generated, You can add-djdk.internal.lambda.dumpproxyclasses at run time, add this parameter, and the runtime will output the generated inner class code to a file

Final class lambda$ $Lambda implements Print {  private lambda$ $Lambda $ ();  public void print (Java.lang.Object);}

If you run Javap-c-P then the results are as follows

Final class lambda$ $Lambda implements Print {  private lambda$ $Lambda $ ();    Code:       0:aload_0       1:invokespecial #10                 //Method java/lang/object. " <init> ":() V       4:return public  void print (java.lang.Object);    Code:       0:aload_1       1:checkcast     #14                 //class java/lang/string       4:invokestatic  #20                 Method lambda.lambda$0: (ljava/lang/string;) V       7:return}

By using the bytecode directive above, we can find that the implementation is called Lambda.lambda$0, which is a private static method.

So the final lambda expression is equivalent to the following form

@FunctionalInterfaceinterface print<t> {public    void Print (T x);} public class Lambda {public       static void Printstring (String s, print<string> Print) {        print.print (s);    }    private static void Lambda$0 (String x) {        System.out.println (x);    }    Final class $Lambda implements print{        @Override public        void Print (Object x) {            lambda$0 ((String) x);        }    }    public static void Main (string[] args) {        printstring ("Test", New Lambda (). New $Lambda $ ());}    }

Java 8 Lambda Implementation principle analysis

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.