⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subroutines.java

📁 该开源工具主要用于class文件的操作
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.apache.bcel.verifier.structurals;/* ==================================================================== * 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.generic.*;import org.apache.bcel.verifier.exc.*;import java.awt.Color;import java.util.ArrayList;import java.util.Enumeration;import java.util.HashSet;import java.util.Hashtable;import java.util.Iterator;	/**	 * Instances of this class contain information about the subroutines	 * found in a code array of a method.	 * This implementation considers the top-level (the instructions	 * reachable without a JSR or JSR_W starting off from the first	 * instruction in a code array of a method) being a special subroutine;	 * see getTopLevel() for that.	 * Please note that the definition of subroutines in the Java Virtual	 * Machine Specification, Second Edition is somewhat incomplete.	 * Therefore, JustIce uses an own, more rigid notion.	 * Basically, a subroutine is a piece of code that starts at the target	 * of a JSR of JSR_W instruction and ends at a corresponding RET	 * instruction. Note also that the control flow of a subroutine	 * may be complex and non-linear; and that subroutines may be nested.	 * JustIce also mandates subroutines not to be protected by exception	 * handling code (for the sake of control flow predictability).	 * To understand JustIce's notion of subroutines, please read   *	 * TODO: refer to the paper.	 *	 * @version $Id: Subroutines.java,v 1.1.1.1 2001/10/29 20:00:42 jvanzyl Exp $	 * @author <A HREF="http://www.inf.fu-berlin.de/~ehaase"/>Enver Haase</A>	 * @see #getTopLevel()	 */public class Subroutines{	/**	 * This inner class implements the Subroutine interface.	 */	private class SubroutineImpl implements Subroutine{		/**		 * UNSET, a symbol for an uninitialized localVariable		 * field. This is used for the "top-level" Subroutine;		 * i.e. no subroutine.		 */		private final int UNSET = -1;		/**		 * The Local Variable slot where the first		 * instruction of this subroutine (an ASTORE) stores		 * the JsrInstruction's ReturnAddress in and		 * the RET of this subroutine operates on.		 */		private int localVariable = UNSET;		/** The instructions that belong to this subroutine. */		private HashSet instructions = new HashSet(); // Elements: InstructionHandle				/*		 * Refer to the Subroutine interface for documentation.		 */		public boolean contains(InstructionHandle inst){			return instructions.contains(inst);		}				/**		 * The JSR or JSR_W instructions that define this		 * subroutine by targeting it.		 */		private HashSet theJSRs = new HashSet();				/**		 * The RET instruction that leaves this subroutine.		 */		private InstructionHandle theRET;				/**		 * Returns a String representation of this object, merely		 * for debugging purposes.		 * (Internal) Warning: Verbosity on a problematic subroutine may cause		 * stack overflow errors due to recursive subSubs() calls.		 * Don't use this, then.		 */		public String toString(){			String ret = "Subroutine: Local variable is '"+localVariable+"', JSRs are '"+theJSRs+"', RET is '"+theRET+"', Instructions: '"+instructions.toString()+"'.";						ret += " Accessed local variable slots: '";			int[] alv = getAccessedLocalsIndices();			for (int i=0; i<alv.length; i++){				ret += alv[i]+" ";			}			ret+="'.";			ret += " Recursively (via subsub...routines) accessed local variable slots: '";			alv = getRecursivelyAccessedLocalsIndices();			for (int i=0; i<alv.length; i++){				ret += alv[i]+" ";			}			ret+="'.";			return ret;		}				/**		 * Sets the leaving RET instruction. Must be invoked after all instructions are added.		 * Must not be invoked for top-level 'subroutine'.		 */		void setLeavingRET(){			if (localVariable == UNSET){				throw new AssertionViolatedException("setLeavingRET() called for top-level 'subroutine' or forgot to set local variable first.");			}			Iterator iter = instructions.iterator();			InstructionHandle ret = null;			while(iter.hasNext()){				InstructionHandle actual = (InstructionHandle) iter.next();				if (actual.getInstruction() instanceof RET){					if (ret != null){						throw new StructuralCodeConstraintException("Subroutine with more then one RET detected: '"+ret+"' and '"+actual+"'.");					}					else{						ret = actual;					}				}			}			if (ret == null){				throw new StructuralCodeConstraintException("Subroutine without a RET detected.");			}			if (((RET) ret.getInstruction()).getIndex() != localVariable){				throw new StructuralCodeConstraintException("Subroutine uses '"+ret+"' which does not match the correct local variable '"+localVariable+"'.");			}			theRET = ret;		}						/*		 * Refer to the Subroutine interface for documentation.		 */		public InstructionHandle[] getEnteringJsrInstructions(){			if (this == TOPLEVEL) {				throw new AssertionViolatedException("getLeavingRET() called on top level pseudo-subroutine.");			}			InstructionHandle[] jsrs = new InstructionHandle[theJSRs.size()];			return (InstructionHandle[]) (theJSRs.toArray(jsrs));		}			/**		 * Adds a new JSR or JSR_W that has this subroutine as its target.		 */		public void addEnteringJsrInstruction(InstructionHandle jsrInst){			if ( (jsrInst == null) || (! (jsrInst.getInstruction() instanceof JsrInstruction))){				throw new AssertionViolatedException("Expecting JsrInstruction InstructionHandle.");			}			if (localVariable == UNSET){				throw new AssertionViolatedException("Set the localVariable first!");			}			else{				// Something is wrong when an ASTORE is targeted that does not operate on the same local variable than the rest of the				// JsrInstruction-targets and the RET.				// (We don't know out leader here so we cannot check if we're really targeted!)				if (localVariable != ((ASTORE) (((JsrInstruction) jsrInst.getInstruction()).getTarget().getInstruction())).getIndex()){					throw new AssertionViolatedException("Setting a wrong JsrInstruction.");				}			}			theJSRs.add(jsrInst);		}		/*		 * Refer to the Subroutine interface for documentation.		 */		public InstructionHandle getLeavingRET(){			if (this == TOPLEVEL) {				throw new AssertionViolatedException("getLeavingRET() called on top level pseudo-subroutine.");			}			return theRET;		}				/*		 * Refer to the Subroutine interface for documentation.		 */		public InstructionHandle[] getInstructions(){			InstructionHandle[] ret = new InstructionHandle[instructions.size()];			return (InstructionHandle[]) instructions.toArray(ret);		}				/*		 * Adds an instruction to this subroutine.		 * All instructions must have been added before invoking setLeavingRET().		 * @see #setLeavingRET		 */		void addInstruction(InstructionHandle ih){			if (theRET != null){				throw new AssertionViolatedException("All instructions must have been added before invoking setLeavingRET().");			}			instructions.add(ih);		}		/* Satisfies Subroutine.getRecursivelyAccessedLocalsIndices(). */		public int[] getRecursivelyAccessedLocalsIndices(){			HashSet s = new HashSet();			int[] lvs = getAccessedLocalsIndices();			for (int j=0; j<lvs.length; j++){				s.add(new Integer(lvs[j]));			}			_getRecursivelyAccessedLocalsIndicesHelper(s, this.subSubs());			int[] ret = new int[s.size()];			Iterator i = s.iterator();			int j=-1;			while (i.hasNext()){				j++;				ret[j] = ((Integer) i.next()).intValue();			}			return ret;		}		/**		 * A recursive helper method for getRecursivelyAccessedLocalsIndices().		 * @see #getRecursivelyAccessedLocalsIndices()		 */		private void _getRecursivelyAccessedLocalsIndicesHelper(HashSet s, Subroutine[] subs){			for (int i=0; i<subs.length; i++){				int[] lvs = subs[i].getAccessedLocalsIndices();				for (int j=0; j<lvs.length; j++){					s.add(new Integer(lvs[j]));				}				if(subs[i].subSubs().length != 0){					_getRecursivelyAccessedLocalsIndicesHelper(s, subs[i].subSubs());				}			}		}		/*		 * Satisfies Subroutine.getAccessedLocalIndices().		 */		public int[] getAccessedLocalsIndices(){			//TODO: Implement caching.			HashSet acc = new HashSet();			if (theRET == null && this != TOPLEVEL){				throw new AssertionViolatedException("This subroutine object must be built up completely before calculating accessed locals.");			}			Iterator i = instructions.iterator();			while (i.hasNext()){				InstructionHandle ih = (InstructionHandle) i.next();				// RET is not a LocalVariableInstruction in the current version of BCEL.				if (ih.getInstruction() instanceof LocalVariableInstruction || ih.getInstruction() instanceof RET){					int idx = ((IndexedInstruction) (ih.getInstruction())).getIndex();					acc.add(new Integer(idx));					// LONG? DOUBLE?.					try{						// LocalVariableInstruction instances are typed without the need to look into						// the constant pool.						if (ih.getInstruction() instanceof LocalVariableInstruction){							int s = ((LocalVariableInstruction) ih.getInstruction()).getType(null).getSize();							if (s==2) acc.add(new Integer(idx+1));						}					}					catch(RuntimeException re){						throw new AssertionViolatedException("Oops. BCEL did not like NULL as a ConstantPoolGen object.");					}				}			}						int[] ret = new int[acc.size()];			i = acc.iterator();			int j=-1;			while (i.hasNext()){				j++;				ret[j] = ((Integer) i.next()).intValue();			}			return ret;		}		/*		 * Satisfies Subroutine.subSubs().		 */		public Subroutine[] subSubs(){			HashSet h = new HashSet();			Iterator i = instructions.iterator();			while (i.hasNext()){				Instruction inst = ((InstructionHandle) i.next()).getInstruction();				if (inst instanceof JsrInstruction){					InstructionHandle targ = ((JsrInstruction) inst).getTarget();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -