Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Openjdk/test/langtools/tools/javac/lambda/   (Sun/Oracle ©)  Datei vom 13.11.2022 mit Größe 25 kB image not shown  

Quelle  ByteCodeTest.java   Sprache: JAVA

 
/*
 * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


/*
 * @test
 * @bug     8011738
 * @author  sogoel
 * @summary Code translation test for Lambda expressions, method references
 * @modules jdk.jdeps/com.sun.tools.classfile
 * @run main ByteCodeTest
 */


import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.BootstrapMethods_attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.ConstantPool.*;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

public class ByteCodeTest {

    static boolean IS_DEBUG = false;
    public static void main(String[] args) {
        File classFile = null;
        int err = 0;
        boolean verifyResult = false;
        for(TestCases tc : TestCases.values()) {
            classFile = getCompiledFile(tc.name(), tc.srcCode);
            if(classFile == null) { // either testFile or classFile was not created
               err++;
            } else {
                verifyResult = verifyClassFileAttributes(classFile, tc);
                if(!verifyResult)
                    System.out.println("Bootstrap class file attributes did not match for " + tc.name());
            }
        }
        if(err > 0)
            throw new RuntimeException("Found " + err + " found");
        else
            System.out.println("Test passed");
    }

    private static boolean verifyClassFileAttributes(File classFile, TestCases tc) {
        ClassFile c = null;
        try {
            c = ClassFile.read(classFile);
        } catch (IOException | ConstantPoolException e) {
            e.printStackTrace();
        }
        ConstantPoolVisitor cpv = new ConstantPoolVisitor(c, c.constant_pool.size());
        Map<Integer, String> hm = cpv.getBSMMap();

        List<String> expectedValList = tc.getExpectedArgValues();
        expectedValList.add(tc.bsmSpecifier.specifier);
        if(!(hm.values().containsAll(new HashSet<String>(expectedValList)))) {
            System.out.println("Values do not match");
            return false;
        }
        return true;
    }

    private static File getCompiledFile(String fname, String srcString) {
        File testFile = null, classFile = null;
        boolean isTestFileCreated = true;

        try {
            testFile = writeTestFile(fname+".java", srcString);
        } catch(IOException ioe) {
            isTestFileCreated = false;
            System.err.println("fail to write" + ioe);
        }

        if(isTestFileCreated) {
            try {
                classFile = compile(testFile);
            } catch (Error err) {
                System.err.println("fail compile. Source:\n" + srcString);
                throw err;
            }
        }
        return classFile;
    }

    static File writeTestFile(String fname, String source) throws IOException {
        File f = new File(fname);
          PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
          out.println(source);
          out.close();
          return f;
    }

    static File compile(File f) {
        int rc = com.sun.tools.javac.Main.compile(new String[] {
                "-g", f.getPath() });
        if (rc != 0)
                throw new Error("compilation failed. rc=" + rc);
            String path = f.getPath();
            return new File(path.substring(0, path.length() - 5) + ".class");
    }

    static void debugln(String str) {
        if(IS_DEBUG)
            System.out.println(str);
    }

    enum BSMSpecifier {
        SPECIFIER1("REF_invokeStatic java/lang/invoke/LambdaMetafactory metaFactory " +
                "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" +
                "Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)" +
                "Ljava/lang/invoke/CallSite;"),
        SPECIFIER2("REF_invokeStatic java/lang/invoke/LambdaMetafactory altMetaFactory " +
                        "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" +
                        "[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;");

        String specifier;
        private BSMSpecifier(String specifier) {
            this.specifier = specifier;
        }
    }

    enum TestCases {
        // Single line lambda expression
        TC1("class TC1 {\n" +
            " public static void main(String[] args) {\n" +
            " Object o = (Runnable) () -> { System.out.println(\"hi\");};\n" +
            " }\n"+
            "}", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface java/lang/Runnable run ()V");
                valList.add("REF_invokeStatic TC1 lambda$0 ()V");
                valList.add("()V");
                return valList;
            }
        },

        // Lambda expression in a for loop
        TC2("import java.util.*;\n" +
            "public class TC2 {\n" +
            " void TC2_test() {\n" +
            " List list = new ArrayList<>();\n" +
            " list.add(\"A\");\n" +
            " list.add(\"B\");\n" +
            " list.stream().forEach( s -> { System.out.println(s); } );\n" +
            " }\n" +
            " public static void main(String[] args) {\n" +
            " new TC2().TC2_test();\n" +
            " }\n" +
            "}", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface java/util/function/Consumer accept (Ljava/lang/Object;)V");
                valList.add("REF_invokeStatic TC2 lambda$0 (Ljava/lang/String;)V");
                valList.add("(Ljava/lang/String;)V");
                return valList;
            }
        },

        // Lambda initializer
        TC3("class TC3 {\n" +
            " interface SAM {\n" +
            " void m(int i);\n" +
            " }\n" +
            " SAM lambda_03 = (int pos) -> { };\n" +
            "}", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC3$SAM m (I)V");
                valList.add("REF_invokeStatic TC3 lambda$0 (I)V");
                valList.add("(I)V");
                return valList;
            }
        },

        // Array initializer
        TC4("class TC4 {\n" +
            " interface Block {\n" +
            " void m(T t);\n" +
            " }\n" +
            " void test1() {\n" +
            " Block[] arr1 = { t -> { }, t -> { } };\n" +
            " }\n" +
            "}", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC4$Block m (Ljava/lang/Object;)V");
                valList.add("REF_invokeStatic TC4 lambda$0 (Ljava/lang/Object;)V");
                valList.add("(Ljava/lang/Object;)V");
                valList.add("REF_invokeStatic TC4 lambda$1 (Ljava/lang/Object;)V");
                return valList;
            }
        },

        //Lambda expression as a method arg
        TC5("class TC5 {\n"+
            " interface MapFun { R m( T n); }\n" +
            " void meth( MapFun mf ) {\n" +
            " assert( mf.m(\"four\") == 4);\n" +
            " }\n"+
            " void test(Integer i) {\n" +
            " meth(s -> { Integer len = s.length(); return len; } );\n" +
            " }\n"+
            "}", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC5$MapFun m (Ljava/lang/Object;)Ljava/lang/Object;");
                valList.add("REF_invokeStatic TC5 lambda$0 (Ljava/lang/String;)Ljava/lang/Integer;");
                valList.add("(Ljava/lang/String;)Ljava/lang/Integer;");
                return valList;
            }
        },

        //Inner class of Lambda expression
        TC6("class TC6 {\n" +
            " interface MapFun { R m( T n); }\n" +
            " MapFun,String> cs;\n" +
            " void test() {\n" +
            " cs = c -> {\n" +
            " class innerClass {\n" +
            " Class icc;\n" +
            " innerClass(Class _c) { icc = _c; }\n" +
            " String getString() { return icc.toString(); }\n" +
            " }\n" +
            " return new innerClass(c).getString();\n"+
            " };\n" +
            " }\n" +
            "}\n", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC6$MapFun m (Ljava/lang/Object;)Ljava/lang/Object;");
                valList.add("REF_invokeSpecial TC6 lambda$0 (Ljava/lang/Class;)Ljava/lang/String;");
                valList.add("(Ljava/lang/Class;)Ljava/lang/String;");
                return valList;
            }
        },

        // Method reference
        TC7("class TC7 {\n" +
            " static interface SAM {\n" +
            " void m(Integer i);\n" +
            " }\n" +
            " void m(Integer i) {}\n" +
            " SAM s = this::m;\n" +
            "}\n", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC7$SAM m (Ljava/lang/Integer;)V");
                valList.add("REF_invokeVirtual TC7 m (Ljava/lang/Integer;)V");
                valList.add("(Ljava/lang/Integer;)V");
                return valList;
            }
        },

        // Constructor reference
        TC8("public class TC8 {\n" +
            " static interface A {Fee m();}\n" +
            " static class Fee {\n" +
            " private T t;\n" +
            " public Fee() {}\n" +
            " }\n" +
            " public static void main(String[] args) {\n" +
            " A a = Fee::new; \n" +
            " }\n" +
            "}\n", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC8$A m ()LTC8$Fee;");
                valList.add("REF_newInvokeSpecial TC8$Fee ()V");
                valList.add("()LTC8$Fee;");
                return valList;
            }
        },

        // Recursive lambda expression
        TC9("class TC9 {\n" +
            " interface Recursive { T apply(R n); };\n" +
            " Recursive factorial;\n" +
            " void test(Integer j) {\n" +
            " factorial = i -> { return i == 0 ? 1 : i * factorial.apply( i - 1 ); };\n" +
            " }\n" +
            "}\n", BSMSpecifier.SPECIFIER1) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeInterface TC9$Recursive apply (Ljava/lang/Object;)Ljava/lang/Object;");
                valList.add("REF_invokeSpecial TC9 lambda$0 (Ljava/lang/Integer;)Ljava/lang/Integer;");
                valList.add("(Ljava/lang/Integer;)Ljava/lang/Integer;");
                return valList;
            }
        },

        //Serializable Lambda
        TC10("import java.io.Serializable;\n" +
              "class TC10 {\n" +
              " interface Foo { int m(); }\n" +
              " public static void main(String[] args) {\n" +
              " Foo f1 = (Foo & Serializable)() -> 3;\n" +
              " }\n" +
              "}\n", BSMSpecifier.SPECIFIER2) {

            @Override
            List<String> getExpectedArgValues() {
                List<String> valList = new ArrayList<>();
                valList.add("REF_invokeStatic java/lang/invoke/LambdaMetafactory altMetaFactory (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;");
                valList.add("REF_invokeInterface TC10$Foo m ()I");
                valList.add("REF_invokeStatic TC10 lambda$main$3231c38a$0 ()I");
                valList.add("()I");
                valList.add("1");
                return valList;
            }
        };

        String srcCode;
        BSMSpecifier bsmSpecifier;

        TestCases(String src, BSMSpecifier bsmSpecifier) {
            this.srcCode = src;
            // By default, all test cases will have bootstrap method specifier as Lambda.MetaFactory
            // For serializable lambda test cases, bootstrap method specifier changed to altMetaFactory
            this.bsmSpecifier = bsmSpecifier;
        }

        List<String> getExpectedArgValues() {
            return null;
        }

        void setSrcCode(String src) {
            srcCode = src;
        }
    }

    static class ConstantPoolVisitor implements ConstantPool.Visitor<String, Integer> {
        final List<String> slist;
        final ClassFile cf;
        final ConstantPool cfpool;
        final Map<Integer, String> bsmMap;


        public ConstantPoolVisitor(ClassFile cf, int size) {
            slist = new ArrayList<>(size);
            for (int i = 0 ; i < size; i++) {
                slist.add(null);
            }
            this.cf = cf;
            this.cfpool = cf.constant_pool;
            bsmMap = readBSM();
        }

        public Map<Integer, String> getBSMMap() {
            return Collections.unmodifiableMap(bsmMap);
        }

        public String visit(CPInfo c, int index) {
            return c.accept(this, index);
        }

        private Map<Integer, String> readBSM() {
            BootstrapMethods_attribute bsmAttr =
                    (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods);
            if (bsmAttr != null) {
                Map<Integer, String> out =
                        new HashMap<>(bsmAttr.bootstrap_method_specifiers.length);
                for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms :
                        bsmAttr.bootstrap_method_specifiers) {
                    int index = bsms.bootstrap_method_ref;
                    try {
                        String value = slist.get(index);
                        if (value == null) {
                            value = visit(cfpool.get(index), index);
                            debugln("[SG]: index " + index);
                            debugln("[SG]: value " + value);
                            slist.set(index, value);
                            out.put(index, value);
                        }
                        for (int idx : bsms.bootstrap_arguments) {
                            value = slist.get(idx);
                            if (value == null) {
                                value = visit(cfpool.get(idx), idx);
                                debugln("[SG]: idx " + idx);
                                debugln("[SG]: value " + value);
                                slist.set(idx, value);
                                out.put(idx, value);
                            }
                        }
                    } catch (InvalidIndex ex) {
                        ex.printStackTrace();
                    }
                }
                return out;
            }
            return new HashMap<>(0);
        }

        @Override
        public String visitClass(CONSTANT_Class_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.name_index), c.name_index);
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitDouble(CONSTANT_Double_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                value = Double.toString(c.value);
                slist.set(p, value);
            }
            return value;
        }

        @Override
        public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) {

        String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.class_index), c.class_index);
                    value = value.concat(" " + visit(cfpool.get(c.name_and_type_index),
                                         c.name_and_type_index));
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitFloat(CONSTANT_Float_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                value = Float.toString(c.value);
                slist.set(p, value);
            }
            return value;
        }

        @Override
        public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                value = Integer.toString(cnstnt.value);
                slist.set(p, value);
            }
            return value;
        }

        @Override
        public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c,
                                              Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.class_index), c.class_index);
                    value = value.concat(" " +
                                         visit(cfpool.get(c.name_and_type_index),
                                         c.name_and_type_index));
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = bsmMap.get(c.bootstrap_method_attr_index) + " "
                            + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index);
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitDynamicConstant(CONSTANT_Dynamic_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = bsmMap.get(c.bootstrap_method_attr_index) + " "
                            + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index);
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitLong(CONSTANT_Long_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                value = Long.toString(c.value);
                slist.set(p, value);
            }
            return value;
        }

        @Override
        public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.name_index), c.name_index);
                    value = value.concat(" " +
                            visit(cfpool.get(c.type_index), c.type_index));
                    slist.set(p, value);
                } catch (InvalidIndex ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitMethodref(CONSTANT_Methodref_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.class_index), c.class_index);
                    value = value.concat(" " +
                                         visit(cfpool.get(c.name_and_type_index),
                                         c.name_and_type_index));
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) {

        String value = slist.get(p);
            if (value == null) {
                try {
                    value = c.reference_kind.name();
                    value = value.concat(" "
                            + visit(cfpool.get(c.reference_index), c.reference_index));
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitMethodType(CONSTANT_MethodType_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.descriptor_index), c.descriptor_index);
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitModule(CONSTANT_Module_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.name_index), c.name_index);
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitPackage(CONSTANT_Package_info c, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                try {
                    value = visit(cfpool.get(c.name_index), c.name_index);
                    slist.set(p, value);
                } catch (ConstantPoolException ex) {
                    ex.printStackTrace();
                }
            }
            return value;
        }

        @Override
        public String visitString(CONSTANT_String_info c, Integer p) {

            try {
                String value = slist.get(p);
                if (value == null) {
                    value = c.getString();
                    slist.set(p, value);
                }
                return value;
            } catch (ConstantPoolException ex) {
                throw new RuntimeException("Fatal error", ex);
            }
        }

        @Override
        public String  visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) {

            String value = slist.get(p);
            if (value == null) {
                value = cnstnt.value;
                slist.set(p, value);
            }
            return value;
        }
    }
}

90%


¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.