Tue, 30 Apr 2013 15:43:00 -0700
8013531: Provide a utility class in com.sun.tools.classfile to find field/method references
Reviewed-by: alanb
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 +