8013531: Provide a utility class in com.sun.tools.classfile to find field/method references

Tue, 30 Apr 2013 15:43:00 -0700

author
mchung
date
Tue, 30 Apr 2013 15:43:00 -0700
changeset 1715
57648bad3287
parent 1714
f3f3ac1273e8
child 1716
260013a710ef

8013531: Provide a utility class in com.sun.tools.classfile to find field/method references
Reviewed-by: alanb

src/share/classes/com/sun/tools/classfile/Dependencies.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/classfile/ReferenceFinder.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/classfile/Dependencies.java	Fri Apr 26 15:59:39 2013 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/classfile/Dependencies.java	Tue Apr 30 15:43:00 2013 -0700
     1.3 @@ -315,7 +315,7 @@
     1.4      static class SimpleLocation implements Location {
     1.5          public SimpleLocation(String name) {
     1.6              this.name = name;
     1.7 -            this.className = name.replace('/', '.').replace('$', '.');
     1.8 +            this.className = name.replace('/', '.');
     1.9          }
    1.10  
    1.11          public String getName() {
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/share/classes/com/sun/tools/classfile/ReferenceFinder.java	Tue Apr 30 15:43:00 2013 -0700
     2.3 @@ -0,0 +1,240 @@
     2.4 +/*
     2.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.  Oracle designates this
    2.11 + * particular file as subject to the "Classpath" exception as provided
    2.12 + * by Oracle in the LICENSE file that accompanied this code.
    2.13 + *
    2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 + * version 2 for more details (a copy is included in the LICENSE file that
    2.18 + * accompanied this code).
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License version
    2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 + *
    2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 + * or visit www.oracle.com if you need additional information or have any
    2.26 + * questions.
    2.27 + */
    2.28 +
    2.29 +package com.sun.tools.classfile;
    2.30 +
    2.31 +import java.util.ArrayList;
    2.32 +import java.util.HashSet;
    2.33 +import java.util.List;
    2.34 +import java.util.Objects;
    2.35 +import java.util.Set;
    2.36 +import com.sun.tools.classfile.Instruction.TypeKind;
    2.37 +import static com.sun.tools.classfile.ConstantPool.*;
    2.38 +
    2.39 +/**
    2.40 + * A utility class to find where in a ClassFile references
    2.41 + * a {@link CONSTANT_Methodref_info method},
    2.42 + * a {@link CONSTANT_InterfaceMethodref_info interface method,
    2.43 + * or a {@link CONSTANT_Fieldref_info field}.
    2.44 + */
    2.45 +public final class ReferenceFinder {
    2.46 +    /**
    2.47 +     * Filter for ReferenceFinder of what constant pool entries for reference lookup.
    2.48 +     */
    2.49 +    public interface Filter {
    2.50 +        /**
    2.51 +         * Decides if the given CPRefInfo entry should be accepted or filtered.
    2.52 +         *
    2.53 +         * @param cpool  ConstantPool of the ClassFile being parsed
    2.54 +         * @param cpref  constant pool entry representing a reference to
    2.55 +         *               a fields method, and interface method.
    2.56 +         * @return {@code true} if accepted; otherwise {@code false}
    2.57 +         */
    2.58 +        boolean accept(ConstantPool cpool, CPRefInfo cpref);
    2.59 +    }
    2.60 +
    2.61 +    /**
    2.62 +     * Visitor of individual method of a ClassFile that references the
    2.63 +     * accepted field, method, or interface method references.
    2.64 +     */
    2.65 +    public interface Visitor {
    2.66 +        /**
    2.67 +         * Invoked for a method containing one or more accepted CPRefInfo entries
    2.68 +         *
    2.69 +         * @param cf      ClassFile
    2.70 +         * @param method  Method that does the references the accepted references
    2.71 +         * @param refs    Accepted constant pool method/field reference
    2.72 +         */
    2.73 +        void visit(ClassFile cf, Method method, List<CPRefInfo> refConstantPool);
    2.74 +    }
    2.75 +
    2.76 +    private final Filter filter;
    2.77 +    private final Visitor visitor;
    2.78 +
    2.79 +    /**
    2.80 +     * Constructor.
    2.81 +     */
    2.82 +    public ReferenceFinder(Filter filter, Visitor visitor) {
    2.83 +        this.filter = Objects.requireNonNull(filter);
    2.84 +        this.visitor = Objects.requireNonNull(visitor);
    2.85 +    }
    2.86 +
    2.87 +    /**
    2.88 +     * Parses a given ClassFile and invoke the visitor if there is any reference
    2.89 +     * to the constant pool entries referencing field, method, or
    2.90 +     * interface method that are accepted. This method will return
    2.91 +     * {@code true} if there is one or more accepted constant pool entries
    2.92 +     * to lookup; otherwise, it will return {@code false}.
    2.93 +     *
    2.94 +     * @param  cf  ClassFile
    2.95 +     * @return {@code true} if the given class file is processed to lookup
    2.96 +     *         references
    2.97 +     * @throws ConstantPoolException if an error of the constant pool
    2.98 +     */
    2.99 +    public boolean parse(ClassFile cf) throws ConstantPoolException {
   2.100 +        List<Integer> cprefs = new ArrayList<Integer>();
   2.101 +        int index = 1;
   2.102 +        for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) {
   2.103 +            if (cpInfo.accept(cpVisitor, cf.constant_pool)) {
   2.104 +                cprefs.add(index);
   2.105 +            }
   2.106 +            index += cpInfo.size();
   2.107 +        }
   2.108 +
   2.109 +        if (cprefs.isEmpty()) {
   2.110 +            return false;
   2.111 +        }
   2.112 +
   2.113 +        for (Method m : cf.methods) {
   2.114 +            Set<Integer> ids = new HashSet<Integer>();
   2.115 +            Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
   2.116 +            if (c_attr != null) {
   2.117 +                for (Instruction instr : c_attr.getInstructions()) {
   2.118 +                    int idx = instr.accept(codeVisitor, cprefs);
   2.119 +                    if (idx > 0) {
   2.120 +                        ids.add(idx);
   2.121 +                    }
   2.122 +                }
   2.123 +            }
   2.124 +            if (ids.size() > 0) {
   2.125 +                List<CPRefInfo> refInfos = new ArrayList<CPRefInfo>(ids.size());
   2.126 +                for (int id : ids) {
   2.127 +                    refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id)));
   2.128 +                }
   2.129 +                visitor.visit(cf, m, refInfos);
   2.130 +            }
   2.131 +        }
   2.132 +        return true;
   2.133 +    }
   2.134 +
   2.135 +    private ConstantPool.Visitor<Boolean,ConstantPool> cpVisitor =
   2.136 +            new ConstantPool.Visitor<Boolean,ConstantPool>()
   2.137 +    {
   2.138 +        public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) {
   2.139 +            return false;
   2.140 +        }
   2.141 +
   2.142 +        public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) {
   2.143 +            return filter.accept(cpool, info);
   2.144 +        }
   2.145 +
   2.146 +        public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) {
   2.147 +            return filter.accept(cpool, info);
   2.148 +        }
   2.149 +
   2.150 +        public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) {
   2.151 +            return filter.accept(cpool, info);
   2.152 +        }
   2.153 +
   2.154 +        public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) {
   2.155 +            return false;
   2.156 +        }
   2.157 +
   2.158 +        public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) {
   2.159 +            return false;
   2.160 +        }
   2.161 +
   2.162 +        public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) {
   2.163 +            return false;
   2.164 +        }
   2.165 +
   2.166 +        public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) {
   2.167 +            return false;
   2.168 +        }
   2.169 +
   2.170 +        public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) {
   2.171 +            return false;
   2.172 +        }
   2.173 +
   2.174 +        public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) {
   2.175 +            return false;
   2.176 +        }
   2.177 +
   2.178 +        public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) {
   2.179 +            return false;
   2.180 +        }
   2.181 +
   2.182 +        public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) {
   2.183 +            return false;
   2.184 +        }
   2.185 +
   2.186 +        public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) {
   2.187 +            return false;
   2.188 +        }
   2.189 +
   2.190 +        public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) {
   2.191 +            return false;
   2.192 +        }
   2.193 +    };
   2.194 +
   2.195 +    private Instruction.KindVisitor<Integer, List<Integer>> codeVisitor =
   2.196 +            new Instruction.KindVisitor<Integer, List<Integer>>()
   2.197 +    {
   2.198 +        public Integer visitNoOperands(Instruction instr, List<Integer> p) {
   2.199 +            return 0;
   2.200 +        }
   2.201 +
   2.202 +        public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) {
   2.203 +            return 0;
   2.204 +        }
   2.205 +
   2.206 +        public Integer visitBranch(Instruction instr, int offset, List<Integer> p) {
   2.207 +            return 0;
   2.208 +        }
   2.209 +
   2.210 +        public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) {
   2.211 +            return p.contains(index) ? index : 0;
   2.212 +        }
   2.213 +
   2.214 +        public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) {
   2.215 +            return p.contains(index) ? index : 0;
   2.216 +        }
   2.217 +
   2.218 +        public Integer visitLocal(Instruction instr, int index, List<Integer> p) {
   2.219 +            return 0;
   2.220 +        }
   2.221 +
   2.222 +        public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) {
   2.223 +            return 0;
   2.224 +        }
   2.225 +
   2.226 +        public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) {
   2.227 +            return 0;
   2.228 +        }
   2.229 +
   2.230 +        public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) {
   2.231 +            return 0;
   2.232 +        }
   2.233 +
   2.234 +        public Integer visitValue(Instruction instr, int value, List<Integer> p) {
   2.235 +            return 0;
   2.236 +        }
   2.237 +
   2.238 +        public Integer visitUnknown(Instruction instr, List<Integer> p) {
   2.239 +            return 0;
   2.240 +        }
   2.241 +    };
   2.242 +}
   2.243 +

mercurial