Mercurial > hg > blitz_stable
view src/com/go/trove/classfile/ConstantPool.java @ 35:6f68e94c1fb8 default tip
Add CondensedStats monitoring utility, equivalent to vmstat
author | Dominic Cleal <dominic-cleal@cdo2.com> |
---|---|
date | Thu, 05 Aug 2010 11:07:25 +0100 |
parents | 3dc0c5604566 |
children |
line wrap: on
line source
/* ==================================================================== * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group * ==================================================================== * The Tea Software License, Version 1.1 * * Copyright (c) 2000 Walt Disney Internet Group. 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 * Walt Disney Internet Group (http://opensource.go.com/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact opensource@dig.com. * * 5. Products derived from this software may not be called "Tea", * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet", * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior * written permission of the Walt Disney Internet Group. * * 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 WALT DISNEY INTERNET GROUP 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. * ==================================================================== * * For more information about Tea, please see http://opensource.go.com/. */ package com.go.trove.classfile; import java.util.*; import java.io.*; /****************************************************************************** * This class corresponds to the constant_pool structure as defined in * section 4.4 of <i>The Java Virtual Machine Specification</i>. * * <p>ConstantPool entries are not written out in the order in which they were * added to it. Instead, their ordering is changed such that String, Integer * and Float constants are written out first. This provides a slight * optimization for referencing these constants from a code attribute. * It means that Opcode.LDC will more likely be used (one-byte index) than * Opcode.LDC_W (two-byte index). * * @author Brian S O'Neill * @version * <!--$$Revision: 1.1 $-->, <!--$$JustDate:--> 9/07/00 <!-- $--> * @see CodeAttr * @see Opcode */ public class ConstantPool { // A set of ConstantInfo objects. private Map mConstants = new HashMap(); // Indexed list of constants. private Vector mIndexedConstants; private int mEntries; // Preserve the order only if the constant pool was read in. private boolean mPreserveOrder; ConstantPool() { } private ConstantPool(Vector indexedConstants) { mIndexedConstants = indexedConstants; int size = indexedConstants.size(); for (int i=1; i<size; i++) { ConstantInfo ci = (ConstantInfo)indexedConstants.get(i); if (ci != null) { mConstants.put(ci, ci); mEntries += ci.getEntryCount(); } } mPreserveOrder = true; } /** * Returns a constant from the pool by index, or throws an exception if not * found. If this constant pool has not yet been written or was not created * by the read method, indexes are not assigned. * * @throws ArrayIndexOutOfBoundsException if index is out of range. */ public ConstantInfo getConstant(int index) { if (mIndexedConstants == null) { throw new ArrayIndexOutOfBoundsException ("Constant pool indexes have not been assigned"); } return (ConstantInfo)mIndexedConstants.get(index); } /** * Returns all the constants in the pool, in no particular order. */ public Set getAllConstants() { return Collections.unmodifiableSet(mConstants.keySet()); } /** * Returns the number of constants in the pool. */ public int getSize() { return mEntries; } /** * Get or create a constant from the constant pool representing a class. */ public ConstantClassInfo addConstantClass(String className) { return ConstantClassInfo.make(this, className); } /** * Get or create a constant from the constant pool representing an array * class. * * @param dim Number of array dimensions. */ public ConstantClassInfo addConstantClass(String className, int dim) { return ConstantClassInfo.make(this, className, dim); } /** * Get or create a constant from the constant pool representing a class. */ public ConstantClassInfo addConstantClass(TypeDescriptor type) { return ConstantClassInfo.make(this, type); } /** * Get or create a constant from the constant pool representing a field in * any class. */ public ConstantFieldInfo addConstantField(String className, String fieldName, TypeDescriptor type) { return ConstantFieldInfo.make (this, ConstantClassInfo.make(this, className), ConstantNameAndTypeInfo.make(this, fieldName, type)); } /** * Get or create a constant from the constant pool representing a method * in any class. If the method returns void, set ret to null. */ public ConstantMethodInfo addConstantMethod(String className, String methodName, TypeDescriptor ret, TypeDescriptor[] params) { MethodDescriptor md = new MethodDescriptor(ret, params); return ConstantMethodInfo.make (this, ConstantClassInfo.make(this, className), ConstantNameAndTypeInfo.make(this, methodName, md)); } /** * Get or create a constant from the constant pool representing an * interface method in any interface. */ public ConstantInterfaceMethodInfo addConstantInterfaceMethod (String className, String methodName, TypeDescriptor ret, TypeDescriptor[] params) { MethodDescriptor md = new MethodDescriptor(ret, params); return ConstantInterfaceMethodInfo.make (this, ConstantClassInfo.make(this, className), ConstantNameAndTypeInfo.make(this, methodName, md)); } /** * Get or create a constant from the constant pool representing a * constructor in any class. */ public ConstantMethodInfo addConstantConstructor(String className, TypeDescriptor[] params) { return addConstantMethod(className, "<init>", null, params); } /** * Get or create a constant integer from the constant pool. */ public ConstantIntegerInfo addConstantInteger(int value) { return ConstantIntegerInfo.make(this, value); } /** * Get or create a constant long from the constant pool. */ public ConstantLongInfo addConstantLong(long value) { return ConstantLongInfo.make(this, value); } /** * Get or create a constant float from the constant pool. */ public ConstantFloatInfo addConstantFloat(float value) { return ConstantFloatInfo.make(this, value); } /** * Get or create a constant double from the constant pool. */ public ConstantDoubleInfo addConstantDouble(double value) { return ConstantDoubleInfo.make(this, value); } /** * Get or create a constant string from the constant pool. */ public ConstantStringInfo addConstantString(String str) { return ConstantStringInfo.make(this, str); } /** * Get or create a constant UTF string from the constant pool. */ public ConstantUTFInfo addConstantUTF(String str) { return ConstantUTFInfo.make(this, str); } /** * Get or create a constant name and type structure from the constant pool. */ public ConstantNameAndTypeInfo addConstantNameAndType(String name, Descriptor type) { return ConstantNameAndTypeInfo.make(this, name, type); } /** * Will only insert into the pool if the constant is not already in the * pool. * * @return The actual constant in the pool. */ public ConstantInfo addConstant(ConstantInfo constant) { ConstantInfo info = (ConstantInfo)mConstants.get(constant); if (info != null) { return info; } int entryCount = constant.getEntryCount(); if (mIndexedConstants != null && mPreserveOrder) { int size = mIndexedConstants.size(); mIndexedConstants.setSize(size + entryCount); mIndexedConstants.set(size, constant); } mConstants.put(constant, constant); mEntries += entryCount; return constant; } public void writeTo(DataOutput dout) throws IOException { // Write out the size (number of entries) of the constant pool. int size = getSize() + 1; // add one because constant 0 is reserved if (size >= 65535) { throw new RuntimeException ("Constant pool entry count cannot exceed 65535: " + size); } dout.writeShort(size); if (mIndexedConstants == null || !mPreserveOrder) { mIndexedConstants = new Vector(size); mIndexedConstants.setSize(size); int index = 1; // one-based constant pool index // First write constants of higher priority -- String, Integer, // Float. // This is a slight optimization. It means that Opcode.LDC will // more likely be used (one-byte index) than Opcode.LDC_W (two-byte // index). Iterator it = mConstants.keySet().iterator(); while (it.hasNext()) { ConstantInfo constant = (ConstantInfo)it.next(); if (constant.hasPriority()) { constant.mIndex = index; mIndexedConstants.set(index, constant); index += constant.getEntryCount(); } } // Now write all non-priority constants. it = mConstants.keySet().iterator(); while (it.hasNext()) { ConstantInfo constant = (ConstantInfo)it.next(); if (!constant.hasPriority()) { constant.mIndex = index; mIndexedConstants.set(index, constant); index += constant.getEntryCount(); } } } // Now actually write out the constants since the indexes have been // resolved. for (int i=1; i<size; i++) { Object obj = mIndexedConstants.get(i); if (obj != null) { ((ConstantInfo)obj).writeTo(dout); } } } public static ConstantPool readFrom(DataInput din) throws IOException { int size = din.readUnsignedShort(); Vector constants = new Vector(size); constants.setSize(size); int index = 1; while (index < size) { int tag = din.readByte(); int entryCount = 1; Object constant; switch (tag) { case ConstantInfo.TAG_UTF8: constant = new ConstantUTFInfo(din.readUTF()); break; case ConstantInfo.TAG_INTEGER: constant = new ConstantIntegerInfo(din.readInt()); break; case ConstantInfo.TAG_FLOAT: constant = new ConstantFloatInfo(din.readFloat()); break; case ConstantInfo.TAG_LONG: constant = new ConstantLongInfo(din.readLong()); entryCount++; break; case ConstantInfo.TAG_DOUBLE: constant = new ConstantDoubleInfo(din.readDouble()); entryCount++; break; case ConstantInfo.TAG_CLASS: case ConstantInfo.TAG_STRING: constant = new TempEntry(tag, din.readUnsignedShort()); break; case ConstantInfo.TAG_FIELD: case ConstantInfo.TAG_METHOD: case ConstantInfo.TAG_INTERFACE_METHOD: case ConstantInfo.TAG_NAME_AND_TYPE: constant = new TempEntry (tag, (din.readShort() << 16) | (din.readUnsignedShort())); break; default: throw new IOException("Invalid constant pool tag: " + tag); } if (constant instanceof ConstantInfo) { ((ConstantInfo)constant).mIndex = index; } constants.set(index, constant); index += entryCount; } for (index = 1; index < size; index++) { resolve(constants, index); } return new ConstantPool(constants); } private static ConstantInfo resolve(List constants, int index) { Object constant = constants.get(index); if (constant == null) { return null; } if (constant instanceof ConstantInfo) { return (ConstantInfo)constant; } TempEntry entry = (TempEntry)constant; int data = entry.mData; int index1 = data & 0xffff; ConstantInfo ci1; Object constant1 = constants.get(index1); if (constant1 instanceof ConstantInfo) { ci1 = (ConstantInfo)constant1; } else { ci1 = resolve(constants, index1); } ConstantInfo ci = null; switch (entry.mTag) { case ConstantInfo.TAG_CLASS: ci = new ConstantClassInfo((ConstantUTFInfo)ci1); break; case ConstantInfo.TAG_STRING: ci = new ConstantStringInfo((ConstantUTFInfo)ci1); break; case ConstantInfo.TAG_FIELD: case ConstantInfo.TAG_METHOD: case ConstantInfo.TAG_INTERFACE_METHOD: case ConstantInfo.TAG_NAME_AND_TYPE: int index2 = data >> 16; ConstantInfo ci2; Object constant2 = constants.get(index2); if (constant2 instanceof ConstantInfo) { ci2 = (ConstantInfo)constant2; } else { ci2 = resolve(constants, index2); } switch (entry.mTag) { case ConstantInfo.TAG_FIELD: ci = new ConstantFieldInfo ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); break; case ConstantInfo.TAG_METHOD: ci = new ConstantMethodInfo ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); break; case ConstantInfo.TAG_INTERFACE_METHOD: ci = new ConstantInterfaceMethodInfo ((ConstantClassInfo)ci2, (ConstantNameAndTypeInfo)ci1); break; case ConstantInfo.TAG_NAME_AND_TYPE: ci = new ConstantNameAndTypeInfo ((ConstantUTFInfo)ci2, (ConstantUTFInfo)ci1); break; } break; } ci.mIndex = index; constants.set(index, ci); return ci; } private static class TempEntry { public int mTag; public int mData; public TempEntry(int tag, int data) { mTag = tag; mData = data; } } }