Path: blob/master/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java
41161 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.classfile;2627import java.util.ArrayList;28import java.util.HashSet;29import java.util.List;30import java.util.Objects;31import java.util.Set;32import com.sun.tools.classfile.Instruction.TypeKind;33import static com.sun.tools.classfile.ConstantPool.*;3435/**36* A utility class to find where in a ClassFile references37* a {@link CONSTANT_Methodref_info method},38* a {@link CONSTANT_InterfaceMethodref_info interface method},39* or a {@link CONSTANT_Fieldref_info field}.40*/41public final class ReferenceFinder {42/**43* Filter for ReferenceFinder of what constant pool entries for reference lookup.44*/45public interface Filter {46/**47* Decides if the given CPRefInfo entry should be accepted or filtered.48*49* @param cpool ConstantPool of the ClassFile being parsed50* @param cpref constant pool entry representing a reference to51* a fields method, and interface method.52* @return {@code true} if accepted; otherwise {@code false}53*/54boolean accept(ConstantPool cpool, CPRefInfo cpref);55}5657/**58* Visitor of individual method of a ClassFile that references the59* accepted field, method, or interface method references.60*/61public interface Visitor {62/**63* Invoked for a method containing one or more accepted CPRefInfo entries64*65* @param cf ClassFile66* @param method Method that does the references the accepted references67* @param refs Accepted constant pool method/field reference68*/69void visit(ClassFile cf, Method method, List<CPRefInfo> refConstantPool);70}7172private final Filter filter;73private final Visitor visitor;7475/**76* Constructor.77*/78public ReferenceFinder(Filter filter, Visitor visitor) {79this.filter = Objects.requireNonNull(filter);80this.visitor = Objects.requireNonNull(visitor);81}8283/**84* Parses a given ClassFile and invoke the visitor if there is any reference85* to the constant pool entries referencing field, method, or86* interface method that are accepted. This method will return87* {@code true} if there is one or more accepted constant pool entries88* to lookup; otherwise, it will return {@code false}.89*90* @param cf ClassFile91* @return {@code true} if the given class file is processed to lookup92* references93* @throws ConstantPoolException if an error of the constant pool94*/95public boolean parse(ClassFile cf) throws ConstantPoolException {96List<Integer> cprefs = new ArrayList<>();97int index = 1;98for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) {99if (cpInfo.accept(cpVisitor, cf.constant_pool)) {100cprefs.add(index);101}102index += cpInfo.size();103}104105if (cprefs.isEmpty()) {106return false;107}108109for (Method m : cf.methods) {110Set<Integer> ids = new HashSet<>();111Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);112if (c_attr != null) {113for (Instruction instr : c_attr.getInstructions()) {114int idx = instr.accept(codeVisitor, cprefs);115if (idx > 0) {116ids.add(idx);117}118}119}120if (ids.size() > 0) {121List<CPRefInfo> refInfos = new ArrayList<>(ids.size());122for (int id : ids) {123refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id)));124}125visitor.visit(cf, m, refInfos);126}127}128return true;129}130131private ConstantPool.Visitor<Boolean,ConstantPool> cpVisitor =132new ConstantPool.Visitor<Boolean,ConstantPool>()133{134public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) {135return false;136}137138public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) {139return filter.accept(cpool, info);140}141142public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) {143return false;144}145146public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) {147return false;148}149150public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) {151return false;152}153154public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) {155return filter.accept(cpool, info);156}157158public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) {159return false;160}161162@Override163public Boolean visitDynamicConstant(CONSTANT_Dynamic_info info, ConstantPool constantPool) {164return false;165}166167public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) {168return false;169}170171public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) {172return false;173}174175public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) {176return filter.accept(cpool, info);177}178179public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) {180return false;181}182183public Boolean visitModule(CONSTANT_Module_info info, ConstantPool cpool) {184return false;185}186187public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) {188return false;189}190191public Boolean visitPackage(CONSTANT_Package_info info, ConstantPool cpool) {192return false;193}194195public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) {196return false;197}198199public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) {200return false;201}202};203204private Instruction.KindVisitor<Integer, List<Integer>> codeVisitor =205new Instruction.KindVisitor<Integer, List<Integer>>()206{207public Integer visitNoOperands(Instruction instr, List<Integer> p) {208return 0;209}210211public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) {212return 0;213}214215public Integer visitBranch(Instruction instr, int offset, List<Integer> p) {216return 0;217}218219public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) {220return p.contains(index) ? index : 0;221}222223public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) {224return p.contains(index) ? index : 0;225}226227public Integer visitLocal(Instruction instr, int index, List<Integer> p) {228return 0;229}230231public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) {232return 0;233}234235public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) {236return 0;237}238239public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) {240return 0;241}242243public Integer visitValue(Instruction instr, int value, List<Integer> p) {244return 0;245}246247public Integer visitUnknown(Instruction instr, List<Integer> p) {248return 0;249}250};251}252253254255