aoqi@0: /* aoqi@0: * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: /* aoqi@0: * @test aoqi@0: * @bug 8011738 aoqi@0: * @author sogoel aoqi@0: * @summary Code translation test for Lambda expressions, method references aoqi@0: * @run main ByteCodeTest aoqi@0: */ aoqi@0: aoqi@0: import com.sun.tools.classfile.Attribute; aoqi@0: import com.sun.tools.classfile.BootstrapMethods_attribute; aoqi@0: import com.sun.tools.classfile.ClassFile; aoqi@0: import com.sun.tools.classfile.ConstantPool; aoqi@0: import com.sun.tools.classfile.ConstantPoolException; aoqi@0: import com.sun.tools.classfile.ConstantPool.*; aoqi@0: aoqi@0: import java.io.BufferedWriter; aoqi@0: import java.io.File; aoqi@0: import java.io.FileWriter; aoqi@0: import java.io.IOException; aoqi@0: import java.io.PrintWriter; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Collections; aoqi@0: import java.util.HashMap; aoqi@0: import java.util.HashSet; aoqi@0: import java.util.List; aoqi@0: import java.util.Map; aoqi@0: aoqi@0: public class ByteCodeTest { aoqi@0: aoqi@0: static boolean IS_DEBUG = false; aoqi@0: public static void main(String[] args) { aoqi@0: File classFile = null; aoqi@0: int err = 0; aoqi@0: boolean verifyResult = false; aoqi@0: for(TestCases tc : TestCases.values()) { aoqi@0: classFile = getCompiledFile(tc.name(), tc.srcCode); aoqi@0: if(classFile == null) { // either testFile or classFile was not created aoqi@0: err++; aoqi@0: } else { aoqi@0: verifyResult = verifyClassFileAttributes(classFile, tc); aoqi@0: if(!verifyResult) aoqi@0: System.out.println("Bootstrap class file attributes did not match for " + tc.name()); aoqi@0: } aoqi@0: } aoqi@0: if(err > 0) aoqi@0: throw new RuntimeException("Found " + err + " found"); aoqi@0: else aoqi@0: System.out.println("Test passed"); aoqi@0: } aoqi@0: aoqi@0: private static boolean verifyClassFileAttributes(File classFile, TestCases tc) { aoqi@0: ClassFile c = null; aoqi@0: try { aoqi@0: c = ClassFile.read(classFile); aoqi@0: } catch (IOException | ConstantPoolException e) { aoqi@0: e.printStackTrace(); aoqi@0: } aoqi@0: ConstantPoolVisitor cpv = new ConstantPoolVisitor(c, c.constant_pool.size()); aoqi@0: Map hm = cpv.getBSMMap(); aoqi@0: aoqi@0: List expectedValList = tc.getExpectedArgValues(); aoqi@0: expectedValList.add(tc.bsmSpecifier.specifier); aoqi@0: if(!(hm.values().containsAll(new HashSet(expectedValList)))) { aoqi@0: System.out.println("Values do not match"); aoqi@0: return false; aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: private static File getCompiledFile(String fname, String srcString) { aoqi@0: File testFile = null, classFile = null; aoqi@0: boolean isTestFileCreated = true; aoqi@0: aoqi@0: try { aoqi@0: testFile = writeTestFile(fname+".java", srcString); aoqi@0: } catch(IOException ioe) { aoqi@0: isTestFileCreated = false; aoqi@0: System.err.println("fail to write" + ioe); aoqi@0: } aoqi@0: aoqi@0: if(isTestFileCreated) { aoqi@0: try { aoqi@0: classFile = compile(testFile); aoqi@0: } catch (Error err) { aoqi@0: System.err.println("fail compile. Source:\n" + srcString); aoqi@0: throw err; aoqi@0: } aoqi@0: } aoqi@0: return classFile; aoqi@0: } aoqi@0: aoqi@0: static File writeTestFile(String fname, String source) throws IOException { aoqi@0: File f = new File(fname); aoqi@0: PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); aoqi@0: out.println(source); aoqi@0: out.close(); aoqi@0: return f; aoqi@0: } aoqi@0: aoqi@0: static File compile(File f) { aoqi@0: int rc = com.sun.tools.javac.Main.compile(new String[] { aoqi@0: "-source", "1.8", "-g", f.getPath() }); aoqi@0: if (rc != 0) aoqi@0: throw new Error("compilation failed. rc=" + rc); aoqi@0: String path = f.getPath(); aoqi@0: return new File(path.substring(0, path.length() - 5) + ".class"); aoqi@0: } aoqi@0: aoqi@0: static void debugln(String str) { aoqi@0: if(IS_DEBUG) aoqi@0: System.out.println(str); aoqi@0: } aoqi@0: aoqi@0: enum BSMSpecifier { aoqi@0: SPECIFIER1("REF_invokeStatic java/lang/invoke/LambdaMetafactory metaFactory " + aoqi@0: "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" + aoqi@0: "Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)" + aoqi@0: "Ljava/lang/invoke/CallSite;"), aoqi@0: SPECIFIER2("REF_invokeStatic java/lang/invoke/LambdaMetafactory altMetaFactory " + aoqi@0: "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" + aoqi@0: "[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"); aoqi@0: aoqi@0: String specifier; aoqi@0: private BSMSpecifier(String specifier) { aoqi@0: this.specifier = specifier; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: enum TestCases { aoqi@0: // Single line lambda expression aoqi@0: TC1("class TC1 {\n" + aoqi@0: " public static void main(String[] args) {\n" + aoqi@0: " Object o = (Runnable) () -> { System.out.println(\"hi\");};\n" + aoqi@0: " }\n"+ aoqi@0: "}", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface java/lang/Runnable run ()V"); aoqi@0: valList.add("REF_invokeStatic TC1 lambda$0 ()V"); aoqi@0: valList.add("()V"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: // Lambda expression in a for loop aoqi@0: TC2("import java.util.*;\n" + aoqi@0: "public class TC2 {\n" + aoqi@0: " void TC2_test() {\n" + aoqi@0: " List list = new ArrayList<>();\n" + aoqi@0: " list.add(\"A\");\n" + aoqi@0: " list.add(\"B\");\n" + aoqi@0: " list.stream().forEach( s -> { System.out.println(s); } );\n" + aoqi@0: " }\n" + aoqi@0: " public static void main(String[] args) {\n" + aoqi@0: " new TC2().TC2_test();\n" + aoqi@0: " }\n" + aoqi@0: "}", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface java/util/function/Consumer accept (Ljava/lang/Object;)V"); aoqi@0: valList.add("REF_invokeStatic TC2 lambda$0 (Ljava/lang/String;)V"); aoqi@0: valList.add("(Ljava/lang/String;)V"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: // Lambda initializer aoqi@0: TC3("class TC3 {\n" + aoqi@0: " interface SAM {\n" + aoqi@0: " void m(int i);\n" + aoqi@0: " }\n" + aoqi@0: " SAM lambda_03 = (int pos) -> { };\n" + aoqi@0: "}", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC3$SAM m (I)V"); aoqi@0: valList.add("REF_invokeStatic TC3 lambda$0 (I)V"); aoqi@0: valList.add("(I)V"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: // Array initializer aoqi@0: TC4("class TC4 {\n" + aoqi@0: " interface Block {\n" + aoqi@0: " void m(T t);\n" + aoqi@0: " }\n" + aoqi@0: " void test1() {\n" + aoqi@0: " Block[] arr1 = { t -> { }, t -> { } };\n" + aoqi@0: " }\n" + aoqi@0: "}", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC4$Block m (Ljava/lang/Object;)V"); aoqi@0: valList.add("REF_invokeStatic TC4 lambda$0 (Ljava/lang/Object;)V"); aoqi@0: valList.add("(Ljava/lang/Object;)V"); aoqi@0: valList.add("REF_invokeStatic TC4 lambda$1 (Ljava/lang/Object;)V"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: //Lambda expression as a method arg aoqi@0: TC5("class TC5 {\n"+ aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " void meth( MapFun mf ) {\n" + aoqi@0: " assert( mf.m(\"four\") == 4);\n" + aoqi@0: " }\n"+ aoqi@0: " void test(Integer i) {\n" + aoqi@0: " meth(s -> { Integer len = s.length(); return len; } );\n" + aoqi@0: " }\n"+ aoqi@0: "}", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC5$MapFun m (Ljava/lang/Object;)Ljava/lang/Object;"); aoqi@0: valList.add("REF_invokeStatic TC5 lambda$0 (Ljava/lang/String;)Ljava/lang/Integer;"); aoqi@0: valList.add("(Ljava/lang/String;)Ljava/lang/Integer;"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: //Inner class of Lambda expression aoqi@0: TC6("class TC6 {\n" + aoqi@0: " interface MapFun { R m( T n); }\n" + aoqi@0: " MapFun,String> cs;\n" + aoqi@0: " void test() {\n" + aoqi@0: " cs = c -> {\n" + aoqi@0: " class innerClass {\n" + aoqi@0: " Class icc;\n" + aoqi@0: " innerClass(Class _c) { icc = _c; }\n" + aoqi@0: " String getString() { return icc.toString(); }\n" + aoqi@0: " }\n" + aoqi@0: " return new innerClass(c).getString();\n"+ aoqi@0: " };\n" + aoqi@0: " }\n" + aoqi@0: "}\n", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC6$MapFun m (Ljava/lang/Object;)Ljava/lang/Object;"); aoqi@0: valList.add("REF_invokeSpecial TC6 lambda$0 (Ljava/lang/Class;)Ljava/lang/String;"); aoqi@0: valList.add("(Ljava/lang/Class;)Ljava/lang/String;"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: // Method reference aoqi@0: TC7("class TC7 {\n" + aoqi@0: " static interface SAM {\n" + aoqi@0: " void m(Integer i);\n" + aoqi@0: " }\n" + aoqi@0: " void m(Integer i) {}\n" + aoqi@0: " SAM s = this::m;\n" + aoqi@0: "}\n", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC7$SAM m (Ljava/lang/Integer;)V"); aoqi@0: valList.add("REF_invokeVirtual TC7 m (Ljava/lang/Integer;)V"); aoqi@0: valList.add("(Ljava/lang/Integer;)V"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: // Constructor reference aoqi@0: TC8("public class TC8 {\n" + aoqi@0: " static interface A {Fee m();}\n" + aoqi@0: " static class Fee {\n" + aoqi@0: " private T t;\n" + aoqi@0: " public Fee() {}\n" + aoqi@0: " }\n" + aoqi@0: " public static void main(String[] args) {\n" + aoqi@0: " A a = Fee::new; \n" + aoqi@0: " }\n" + aoqi@0: "}\n", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC8$A m ()LTC8$Fee;"); aoqi@0: valList.add("REF_newInvokeSpecial TC8$Fee ()V"); aoqi@0: valList.add("()LTC8$Fee;"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: // Recursive lambda expression aoqi@0: TC9("class TC9 {\n" + aoqi@0: " interface Recursive { T apply(R n); };\n" + aoqi@0: " Recursive factorial;\n" + aoqi@0: " void test(Integer j) {\n" + aoqi@0: " factorial = i -> { return i == 0 ? 1 : i * factorial.apply( i - 1 ); };\n" + aoqi@0: " }\n" + aoqi@0: "}\n", BSMSpecifier.SPECIFIER1) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: valList.add("REF_invokeInterface TC9$Recursive apply (Ljava/lang/Object;)Ljava/lang/Object;"); aoqi@0: valList.add("REF_invokeSpecial TC9 lambda$0 (Ljava/lang/Integer;)Ljava/lang/Integer;"); aoqi@0: valList.add("(Ljava/lang/Integer;)Ljava/lang/Integer;"); aoqi@0: return valList; aoqi@0: } aoqi@0: }, aoqi@0: aoqi@0: //Serializable Lambda aoqi@0: TC10("import java.io.Serializable;\n" + aoqi@0: "class TC10 {\n" + aoqi@0: " interface Foo { int m(); }\n" + aoqi@0: " public static void main(String[] args) {\n" + aoqi@0: " Foo f1 = (Foo & Serializable)() -> 3;\n" + aoqi@0: " }\n" + aoqi@0: "}\n", BSMSpecifier.SPECIFIER2) { aoqi@0: aoqi@0: @Override aoqi@0: List getExpectedArgValues() { aoqi@0: List valList = new ArrayList<>(); aoqi@0: 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;"); aoqi@0: valList.add("REF_invokeInterface TC10$Foo m ()I"); aoqi@0: valList.add("REF_invokeStatic TC10 lambda$main$3231c38a$0 ()I"); aoqi@0: valList.add("()I"); aoqi@0: valList.add("1"); aoqi@0: return valList; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: String srcCode; aoqi@0: BSMSpecifier bsmSpecifier; aoqi@0: aoqi@0: TestCases(String src, BSMSpecifier bsmSpecifier) { aoqi@0: this.srcCode = src; aoqi@0: // By default, all test cases will have bootstrap method specifier as Lambda.MetaFactory aoqi@0: // For serializable lambda test cases, bootstrap method specifier changed to altMetaFactory aoqi@0: this.bsmSpecifier = bsmSpecifier; aoqi@0: } aoqi@0: aoqi@0: List getExpectedArgValues() { aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: void setSrcCode(String src) { aoqi@0: srcCode = src; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: static class ConstantPoolVisitor implements ConstantPool.Visitor { aoqi@0: final List slist; aoqi@0: final ClassFile cf; aoqi@0: final ConstantPool cfpool; aoqi@0: final Map bsmMap; aoqi@0: aoqi@0: aoqi@0: public ConstantPoolVisitor(ClassFile cf, int size) { aoqi@0: slist = new ArrayList<>(size); aoqi@0: for (int i = 0 ; i < size; i++) { aoqi@0: slist.add(null); aoqi@0: } aoqi@0: this.cf = cf; aoqi@0: this.cfpool = cf.constant_pool; aoqi@0: bsmMap = readBSM(); aoqi@0: } aoqi@0: aoqi@0: public Map getBSMMap() { aoqi@0: return Collections.unmodifiableMap(bsmMap); aoqi@0: } aoqi@0: aoqi@0: public String visit(CPInfo c, int index) { aoqi@0: return c.accept(this, index); aoqi@0: } aoqi@0: aoqi@0: private Map readBSM() { aoqi@0: BootstrapMethods_attribute bsmAttr = aoqi@0: (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods); aoqi@0: if (bsmAttr != null) { aoqi@0: Map out = aoqi@0: new HashMap<>(bsmAttr.bootstrap_method_specifiers.length); aoqi@0: for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms : aoqi@0: bsmAttr.bootstrap_method_specifiers) { aoqi@0: int index = bsms.bootstrap_method_ref; aoqi@0: try { aoqi@0: String value = slist.get(index); aoqi@0: if (value == null) { aoqi@0: value = visit(cfpool.get(index), index); aoqi@0: debugln("[SG]: index " + index); aoqi@0: debugln("[SG]: value " + value); aoqi@0: slist.set(index, value); aoqi@0: out.put(index, value); aoqi@0: } aoqi@0: for (int idx : bsms.bootstrap_arguments) { aoqi@0: value = slist.get(idx); aoqi@0: if (value == null) { aoqi@0: value = visit(cfpool.get(idx), idx); aoqi@0: debugln("[SG]: idx " + idx); aoqi@0: debugln("[SG]: value " + value); aoqi@0: slist.set(idx, value); aoqi@0: out.put(idx, value); aoqi@0: } aoqi@0: } aoqi@0: } catch (InvalidIndex ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return out; aoqi@0: } aoqi@0: return new HashMap<>(0); aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitClass(CONSTANT_Class_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = visit(cfpool.get(c.name_index), c.name_index); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitDouble(CONSTANT_Double_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: value = Double.toString(c.value); aoqi@0: slist.set(p, value); aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = visit(cfpool.get(c.class_index), c.class_index); aoqi@0: value = value.concat(" " + visit(cfpool.get(c.name_and_type_index), aoqi@0: c.name_and_type_index)); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitFloat(CONSTANT_Float_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: value = Float.toString(c.value); aoqi@0: slist.set(p, value); aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: value = Integer.toString(cnstnt.value); aoqi@0: slist.set(p, value); aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c, aoqi@0: Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = visit(cfpool.get(c.class_index), c.class_index); aoqi@0: value = value.concat(" " + aoqi@0: visit(cfpool.get(c.name_and_type_index), aoqi@0: c.name_and_type_index)); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = bsmMap.get(c.bootstrap_method_attr_index) + " " aoqi@0: + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitLong(CONSTANT_Long_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: value = Long.toString(c.value); aoqi@0: slist.set(p, value); aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = visit(cfpool.get(c.name_index), c.name_index); aoqi@0: value = value.concat(" " + aoqi@0: visit(cfpool.get(c.type_index), c.type_index)); aoqi@0: slist.set(p, value); aoqi@0: } catch (InvalidIndex ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitMethodref(CONSTANT_Methodref_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = visit(cfpool.get(c.class_index), c.class_index); aoqi@0: value = value.concat(" " + aoqi@0: visit(cfpool.get(c.name_and_type_index), aoqi@0: c.name_and_type_index)); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = c.reference_kind.name(); aoqi@0: value = value.concat(" " aoqi@0: + visit(cfpool.get(c.reference_index), c.reference_index)); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitMethodType(CONSTANT_MethodType_info c, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: try { aoqi@0: value = visit(cfpool.get(c.descriptor_index), c.descriptor_index); aoqi@0: slist.set(p, value); aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: ex.printStackTrace(); aoqi@0: } aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitString(CONSTANT_String_info c, Integer p) { aoqi@0: aoqi@0: try { aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: value = c.getString(); aoqi@0: slist.set(p, value); aoqi@0: } aoqi@0: return value; aoqi@0: } catch (ConstantPoolException ex) { aoqi@0: throw new RuntimeException("Fatal error", ex); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: @Override aoqi@0: public String visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) { aoqi@0: aoqi@0: String value = slist.get(p); aoqi@0: if (value == null) { aoqi@0: value = cnstnt.value; aoqi@0: slist.set(p, value); aoqi@0: } aoqi@0: return value; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: