src/share/classes/com/sun/tools/classfile/ReferenceFinder.java

changeset 0
959103a6100f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/classes/com/sun/tools/classfile/ReferenceFinder.java	Wed Apr 27 01:34:52 2016 +0800
     1.3 @@ -0,0 +1,240 @@
     1.4 +/*
     1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.tools.classfile;
    1.30 +
    1.31 +import java.util.ArrayList;
    1.32 +import java.util.HashSet;
    1.33 +import java.util.List;
    1.34 +import java.util.Objects;
    1.35 +import java.util.Set;
    1.36 +import com.sun.tools.classfile.Instruction.TypeKind;
    1.37 +import static com.sun.tools.classfile.ConstantPool.*;
    1.38 +
    1.39 +/**
    1.40 + * A utility class to find where in a ClassFile references
    1.41 + * a {@link CONSTANT_Methodref_info method},
    1.42 + * a {@link CONSTANT_InterfaceMethodref_info interface method,
    1.43 + * or a {@link CONSTANT_Fieldref_info field}.
    1.44 + */
    1.45 +public final class ReferenceFinder {
    1.46 +    /**
    1.47 +     * Filter for ReferenceFinder of what constant pool entries for reference lookup.
    1.48 +     */
    1.49 +    public interface Filter {
    1.50 +        /**
    1.51 +         * Decides if the given CPRefInfo entry should be accepted or filtered.
    1.52 +         *
    1.53 +         * @param cpool  ConstantPool of the ClassFile being parsed
    1.54 +         * @param cpref  constant pool entry representing a reference to
    1.55 +         *               a fields method, and interface method.
    1.56 +         * @return {@code true} if accepted; otherwise {@code false}
    1.57 +         */
    1.58 +        boolean accept(ConstantPool cpool, CPRefInfo cpref);
    1.59 +    }
    1.60 +
    1.61 +    /**
    1.62 +     * Visitor of individual method of a ClassFile that references the
    1.63 +     * accepted field, method, or interface method references.
    1.64 +     */
    1.65 +    public interface Visitor {
    1.66 +        /**
    1.67 +         * Invoked for a method containing one or more accepted CPRefInfo entries
    1.68 +         *
    1.69 +         * @param cf      ClassFile
    1.70 +         * @param method  Method that does the references the accepted references
    1.71 +         * @param refs    Accepted constant pool method/field reference
    1.72 +         */
    1.73 +        void visit(ClassFile cf, Method method, List<CPRefInfo> refConstantPool);
    1.74 +    }
    1.75 +
    1.76 +    private final Filter filter;
    1.77 +    private final Visitor visitor;
    1.78 +
    1.79 +    /**
    1.80 +     * Constructor.
    1.81 +     */
    1.82 +    public ReferenceFinder(Filter filter, Visitor visitor) {
    1.83 +        this.filter = Objects.requireNonNull(filter);
    1.84 +        this.visitor = Objects.requireNonNull(visitor);
    1.85 +    }
    1.86 +
    1.87 +    /**
    1.88 +     * Parses a given ClassFile and invoke the visitor if there is any reference
    1.89 +     * to the constant pool entries referencing field, method, or
    1.90 +     * interface method that are accepted. This method will return
    1.91 +     * {@code true} if there is one or more accepted constant pool entries
    1.92 +     * to lookup; otherwise, it will return {@code false}.
    1.93 +     *
    1.94 +     * @param  cf  ClassFile
    1.95 +     * @return {@code true} if the given class file is processed to lookup
    1.96 +     *         references
    1.97 +     * @throws ConstantPoolException if an error of the constant pool
    1.98 +     */
    1.99 +    public boolean parse(ClassFile cf) throws ConstantPoolException {
   1.100 +        List<Integer> cprefs = new ArrayList<Integer>();
   1.101 +        int index = 1;
   1.102 +        for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) {
   1.103 +            if (cpInfo.accept(cpVisitor, cf.constant_pool)) {
   1.104 +                cprefs.add(index);
   1.105 +            }
   1.106 +            index += cpInfo.size();
   1.107 +        }
   1.108 +
   1.109 +        if (cprefs.isEmpty()) {
   1.110 +            return false;
   1.111 +        }
   1.112 +
   1.113 +        for (Method m : cf.methods) {
   1.114 +            Set<Integer> ids = new HashSet<Integer>();
   1.115 +            Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
   1.116 +            if (c_attr != null) {
   1.117 +                for (Instruction instr : c_attr.getInstructions()) {
   1.118 +                    int idx = instr.accept(codeVisitor, cprefs);
   1.119 +                    if (idx > 0) {
   1.120 +                        ids.add(idx);
   1.121 +                    }
   1.122 +                }
   1.123 +            }
   1.124 +            if (ids.size() > 0) {
   1.125 +                List<CPRefInfo> refInfos = new ArrayList<CPRefInfo>(ids.size());
   1.126 +                for (int id : ids) {
   1.127 +                    refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id)));
   1.128 +                }
   1.129 +                visitor.visit(cf, m, refInfos);
   1.130 +            }
   1.131 +        }
   1.132 +        return true;
   1.133 +    }
   1.134 +
   1.135 +    private ConstantPool.Visitor<Boolean,ConstantPool> cpVisitor =
   1.136 +            new ConstantPool.Visitor<Boolean,ConstantPool>()
   1.137 +    {
   1.138 +        public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) {
   1.139 +            return false;
   1.140 +        }
   1.141 +
   1.142 +        public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) {
   1.143 +            return filter.accept(cpool, info);
   1.144 +        }
   1.145 +
   1.146 +        public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) {
   1.147 +            return filter.accept(cpool, info);
   1.148 +        }
   1.149 +
   1.150 +        public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) {
   1.151 +            return filter.accept(cpool, info);
   1.152 +        }
   1.153 +
   1.154 +        public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) {
   1.155 +            return false;
   1.156 +        }
   1.157 +
   1.158 +        public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) {
   1.159 +            return false;
   1.160 +        }
   1.161 +
   1.162 +        public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) {
   1.163 +            return false;
   1.164 +        }
   1.165 +
   1.166 +        public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) {
   1.167 +            return false;
   1.168 +        }
   1.169 +
   1.170 +        public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) {
   1.171 +            return false;
   1.172 +        }
   1.173 +
   1.174 +        public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) {
   1.175 +            return false;
   1.176 +        }
   1.177 +
   1.178 +        public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) {
   1.179 +            return false;
   1.180 +        }
   1.181 +
   1.182 +        public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) {
   1.183 +            return false;
   1.184 +        }
   1.185 +
   1.186 +        public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) {
   1.187 +            return false;
   1.188 +        }
   1.189 +
   1.190 +        public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) {
   1.191 +            return false;
   1.192 +        }
   1.193 +    };
   1.194 +
   1.195 +    private Instruction.KindVisitor<Integer, List<Integer>> codeVisitor =
   1.196 +            new Instruction.KindVisitor<Integer, List<Integer>>()
   1.197 +    {
   1.198 +        public Integer visitNoOperands(Instruction instr, List<Integer> p) {
   1.199 +            return 0;
   1.200 +        }
   1.201 +
   1.202 +        public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) {
   1.203 +            return 0;
   1.204 +        }
   1.205 +
   1.206 +        public Integer visitBranch(Instruction instr, int offset, List<Integer> p) {
   1.207 +            return 0;
   1.208 +        }
   1.209 +
   1.210 +        public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) {
   1.211 +            return p.contains(index) ? index : 0;
   1.212 +        }
   1.213 +
   1.214 +        public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) {
   1.215 +            return p.contains(index) ? index : 0;
   1.216 +        }
   1.217 +
   1.218 +        public Integer visitLocal(Instruction instr, int index, List<Integer> p) {
   1.219 +            return 0;
   1.220 +        }
   1.221 +
   1.222 +        public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) {
   1.223 +            return 0;
   1.224 +        }
   1.225 +
   1.226 +        public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) {
   1.227 +            return 0;
   1.228 +        }
   1.229 +
   1.230 +        public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) {
   1.231 +            return 0;
   1.232 +        }
   1.233 +
   1.234 +        public Integer visitValue(Instruction instr, int value, List<Integer> p) {
   1.235 +            return 0;
   1.236 +        }
   1.237 +
   1.238 +        public Integer visitUnknown(Instruction instr, List<Integer> p) {
   1.239 +            return 0;
   1.240 +        }
   1.241 +    };
   1.242 +}
   1.243 +

mercurial