📄 pass2verifier.java
字号:
package org.apache.bcel.verifier.statics;/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" and * "Apache BCEL" must not be used to endorse or promote products * derived from this software without prior written permission. For * written permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * "Apache BCEL", nor may "Apache" appear in their name, without * prior written permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */import org.apache.bcel.Constants;import org.apache.bcel.Repository;import org.apache.bcel.classfile.*;import org.apache.bcel.classfile.DescendingVisitor; // Use _this_ one!import org.apache.bcel.classfile.EmptyVisitor; // Use _this_ one!import org.apache.bcel.classfile.Visitor; // Use _this_ one!import org.apache.bcel.generic.*;import org.apache.bcel.verifier.*;import org.apache.bcel.verifier.exc.*;import java.util.HashMap;import java.util.HashSet;/** * This PassVerifier verifies a class file according to * pass 2 as described in The Java Virtual Machine * Specification, 2nd edition. * More detailed information is to be found at the do_verify() * method's documentation. * * @version $Id: Pass2Verifier.java,v 1.1.1.1 2001/10/29 20:00:36 jvanzyl Exp $ * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A> * @see #do_verify() */public final class Pass2Verifier extends PassVerifier implements Constants{ /** * The LocalVariableInfo instances used by Pass3bVerifier. * localVariablesInfos[i] denotes the information for the * local variables of method number i in the * JavaClass this verifier operates on. */ private LocalVariablesInfo[] localVariablesInfos; /** The Verifier that created this. */ private Verifier myOwner; /** * Should only be instantiated by a Verifier. * * @see Verifier */ public Pass2Verifier(Verifier owner){ myOwner = owner; } /** * Returns a LocalVariablesInfo object containing information * about the usage of the local variables in the Code attribute * of the said method or <B>null</B> if the class file this * Pass2Verifier operates on could not be pass-2-verified correctly. * The method number method_nr is the method you get using * <B>Repository.lookupClass(myOwner.getClassname()).getMethods()[method_nr];</B>. * You should not add own information. Leave that to JustIce. */ public LocalVariablesInfo getLocalVariablesInfo(int method_nr){ if (this.verify() != VerificationResult.VR_OK) return null; // It's cached, don't worry. if (method_nr < 0 || method_nr >= localVariablesInfos.length){ throw new AssertionViolatedException("Method number out of range."); } return localVariablesInfos[method_nr]; } /** * Pass 2 is the pass where static properties of the * class file are checked without looking into "Code" * arrays of methods. * This verification pass is usually invoked when * a class is resolved; and it may be possible that * this verification pass has to load in other classes * such as superclasses or implemented interfaces. * Therefore, Pass 1 is run on them.<BR> * Note that most referenced classes are <B>not</B> loaded * in for verification or for an existance check by this * pass; only the syntactical correctness of their names * and descriptors (a.k.a. signatures) is checked.<BR> * Very few checks that conceptually belong here * are delayed until pass 3a in JustIce. JustIce does * not only check for syntactical correctness but also * for semantical sanity - therefore it needs access to * the "Code" array of methods in a few cases. Please * see the pass 3a documentation, too. * * @see org.apache.bcel.verifier.statics.Pass3aVerifier */ public VerificationResult do_verify(){ VerificationResult vr1 = myOwner.doPass1(); if (vr1.equals(VerificationResult.VR_OK)){ // For every method, we could have information about the local variables out of LocalVariableTable attributes of // the Code attributes. localVariablesInfos = new LocalVariablesInfo[Repository.lookupClass(myOwner.getClassName()).getMethods().length]; VerificationResult vr = VerificationResult.VR_OK; // default. try{ constant_pool_entries_satisfy_static_constraints(); field_and_method_refs_are_valid(); every_class_has_an_accessible_superclass(); final_methods_are_not_overridden(); } catch (ClassConstraintException cce){ vr = new VerificationResult(VerificationResult.VERIFIED_REJECTED, cce.getMessage()); } return vr; } else return VerificationResult.VR_NOTYET; } /** * Ensures that every class has a super class and that * <B>final</B> classes are not subclassed. * This means, the class this Pass2Verifier operates * on has proper super classes (transitively) up to * java.lang.Object. * The reason for really loading (and Pass1-verifying) * all of those classes here is that we need them in * Pass2 anyway to verify no final methods are overridden * (that could be declared anywhere in the ancestor hierarchy). * * @throws ClassConstraintException otherwise. */ private void every_class_has_an_accessible_superclass(){ HashSet hs = new HashSet(); // save class names to detect circular inheritance JavaClass jc = Repository.lookupClass(myOwner.getClassName()); int supidx = -1; while (supidx != 0){ supidx = jc.getSuperclassNameIndex(); if (supidx == 0){ if (jc != Repository.lookupClass(Type.OBJECT.getClassName())){ throw new ClassConstraintException("Superclass of '"+jc.getClassName()+"' missing but not "+Type.OBJECT.getClassName()+" itself!"); } } else{ String supername = jc.getSuperclassName(); if (! hs.add(supername)){ // If supername already is in the list throw new ClassConstraintException("Circular superclass hierarchy detected."); } Verifier v = VerifierFactory.getVerifier(supername); VerificationResult vr = v.doPass1(); if (vr != VerificationResult.VR_OK){ throw new ClassConstraintException("Could not load in ancestor class '"+supername+"'."); } jc = Repository.lookupClass(supername); if (jc.isFinal()){ throw new ClassConstraintException("Ancestor class '"+supername+"' has the FINAL access modifier and must therefore not be subclassed."); } } } } /** * Ensures that <B>final</B> methods are not overridden. * <B>Precondition to run this method: * constant_pool_entries_satisfy_static_constraints() and * every_class_has_an_accessible_superclass() have to be invoked before * (in that order).</B> * * @throws ClassConstraintException otherwise. * @see #constant_pool_entries_satisfy_static_constraints() * @see #every_class_has_an_accessible_superclass() */ private void final_methods_are_not_overridden(){ HashMap hashmap = new HashMap(); JavaClass jc = Repository.lookupClass(myOwner.getClassName()); int supidx = -1; while (supidx != 0){ supidx = jc.getSuperclassNameIndex(); ConstantPoolGen cpg = new ConstantPoolGen(jc.getConstantPool()); Method[] methods = jc.getMethods(); for (int i=0; i<methods.length; i++){ String name_and_sig = (methods[i].getName()+methods[i].getSignature()); if (hashmap.containsKey(name_and_sig)){ if (methods[i].isFinal()){ throw new ClassConstraintException("Method '"+name_and_sig+"' in class '"+hashmap.get(name_and_sig)+"' overrides the final (not-overridable) definition in class '"+jc.getClassName()+"'."); } else{ if (!methods[i].isStatic()){ // static methods don't inherit hashmap.put(name_and_sig, jc.getClassName()); } } } else{ if (!methods[i].isStatic()){ // static methods don't inherit hashmap.put(name_and_sig, jc.getClassName()); } } } jc = Repository.lookupClass(jc.getSuperclassName()); // Well, for OBJECT this returns OBJECT so it works (could return anything but must not throw an Exception). } } /** * Ensures that the constant pool entries satisfy the static constraints * as described in The Java Virtual Machine Specification, 2nd Edition. * * @throws ClassConstraintException otherwise. */ private void constant_pool_entries_satisfy_static_constraints(){ // Most of the consistency is handled internally by BCEL; here // we only have to verify if the indices of the constants point // to constants of the appropriate type and such. JavaClass jc = Repository.lookupClass(myOwner.getClassName()); new CPESSC_Visitor(jc); // constructor implicitely traverses jc } /** * A Visitor class that ensures the constant pool satisfies the static * constraints. * The visitXXX() methods throw ClassConstraintException instances otherwise. * * @see #constant_pool_entries_satisfy_static_constraints() */ private class CPESSC_Visitor extends org.apache.bcel.classfile.EmptyVisitor implements Visitor{ private Class CONST_Class; private Class CONST_Fieldref; private Class CONST_Methodref; private Class CONST_InterfaceMethodref; private Class CONST_String; private Class CONST_Integer; private Class CONST_Float; private Class CONST_Long; private Class CONST_Double; private Class CONST_NameAndType; private Class CONST_Utf8; private final JavaClass jc; private final ConstantPool cp; // ==jc.getConstantPool() -- only here to save typing work and computing power. private final int cplen; // == cp.getLength() -- to save computing power. private DescendingVisitor carrier; private HashSet field_names = new HashSet(); private HashSet field_names_and_desc = new HashSet(); private HashSet method_names_and_desc = new HashSet(); private CPESSC_Visitor(JavaClass _jc){ jc = _jc; cp = _jc.getConstantPool(); cplen = cp.getLength(); CONST_Class = org.apache.bcel.classfile.ConstantClass.class; CONST_Fieldref = org.apache.bcel.classfile.ConstantFieldref.class; CONST_Methodref = org.apache.bcel.classfile.ConstantMethodref.class; CONST_InterfaceMethodref = org.apache.bcel.classfile.ConstantInterfaceMethodref.class; CONST_String = org.apache.bcel.classfile.ConstantString.class;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -