/* * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package sun.tools.java;import java.io.IOException;import java.io.DataInputStream;import java.io.DataOutputStream;import java.util.Vector;import java.util.Hashtable;/** * This class is used to represent a constant table once * it is read from a class file. * * WARNING: The contents of this source file are not part of any * supported API. Code that depends on them does so at its own risk: * they are subject to change or removal without notice. */public finalclass BinaryConstantPool implements Constants { private byte types[]; private Object cpool[]; /** * Constructor */ BinaryConstantPool(DataInputStream in) throws IOException { // JVM 4.1 ClassFile.constant_pool_count types = new byte[in.readUnsignedShort()]; cpool = new Object[types.length]; for (int i = 1 ; i < cpool.length ; i++) { int j = i; // JVM 4.4 cp_info.tag switch(types[i] = in.readByte()) { case CONSTANT_UTF8: cpool[i] = in.readUTF(); break; case CONSTANT_INTEGER: cpool[i] = new Integer(in.readInt()); break; case CONSTANT_FLOAT: cpool[i] = new Float(in.readFloat()); break; case CONSTANT_LONG: cpool[i++] = new Long(in.readLong()); break; case CONSTANT_DOUBLE: cpool[i++] = new Double(in.readDouble()); break; case CONSTANT_CLASS: case CONSTANT_STRING: // JVM 4.4.3 CONSTANT_String_info.string_index // or JVM 4.4.1 CONSTANT_Class_info.name_index cpool[i] = new Integer(in.readUnsignedShort()); break; case CONSTANT_FIELD: case CONSTANT_METHOD: case CONSTANT_INTERFACEMETHOD: case CONSTANT_NAMEANDTYPE: // JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort()); break; case 0: default: throw new ClassFormatError("invalid constant type: " + (int)types[i]); } } } /** * get a integer */ public int getInteger(int n) { return (n == 0) ? 0 : ((Number)cpool[n]).intValue(); } /** * get a value */ public Object getValue(int n) { return (n == 0) ? null : cpool[n]; } /** * get a string */ public String getString(int n) { return (n == 0) ? null : (String)cpool[n]; } /** * get an identifier */ public Identifier getIdentifier(int n) { return (n == 0) ? null : Identifier.lookup(getString(n)); } /** * get class declaration */ public ClassDeclaration getDeclarationFromName(Environment env, int n) { return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.'))); } /** * get class declaration */ public ClassDeclaration getDeclaration(Environment env, int n) { return (n == 0) ? null : getDeclarationFromName(env, getInteger(n)); } /** * get a type from a type signature */ public Type getType(int n) { return Type.tType(getString(n)); } /** * get the type of constant given an index */ public int getConstantType(int n) { return types[n]; } /** * get the n-th constant from the constant pool */ public Object getConstant(int n, Environment env) { int constant_type = getConstantType(n); switch (constant_type) { case CONSTANT_INTEGER: case CONSTANT_FLOAT: case CONSTANT_LONG: case CONSTANT_DOUBLE: return getValue(n); case CONSTANT_CLASS: return getDeclaration(env, n); case CONSTANT_STRING: return getString(getInteger(n)); case CONSTANT_FIELD: case CONSTANT_METHOD: case CONSTANT_INTERFACEMETHOD: try { int key = getInteger(n); ClassDefinition clazz = getDeclaration(env, key >> 16).getClassDefinition(env); int name_and_type = getInteger(key & 0xFFFF); Identifier id = getIdentifier(name_and_type >> 16); Type type = getType(name_and_type & 0xFFFF); for (MemberDefinition field = clazz.getFirstMatch(id); field != null; field = field.getNextMatch()) { Type field_type = field.getType(); if ((constant_type == CONSTANT_FIELD) ? (field_type == type) : (field_type.equalArguments(type))) return field; } } catch (ClassNotFound e) { } return null; default: throw new ClassFormatError("invalid constant type: " + constant_type); } } /** * Get a list of dependencies, ie: all the classes referenced in this * constant pool. */ public Vector getDependencies(Environment env) { Vector v = new Vector(); for (int i = 1 ; i < cpool.length ; i++) { switch(types[i]) { case CONSTANT_CLASS: v.addElement(getDeclarationFromName(env, getInteger(i))); break; } } return v; } Hashtable indexHashObject, indexHashAscii; Vector MoreStuff; /** * Find the index of an Object in the constant pool */ public int indexObject(Object obj, Environment env) { if (indexHashObject == null) createIndexHash(env); Integer result = (Integer)indexHashObject.get(obj); if (result == null) throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " + obj.getClass() + " in constant pool"); return result.intValue(); } /** * Find the index of an ascii string in the constant pool. If it's not in * the constant pool, then add it at the end. */ public int indexString(String string, Environment env) { if (indexHashObject == null) createIndexHash(env); Integer result = (Integer)indexHashAscii.get(string); if (result == null) { if (MoreStuff == null) MoreStuff = new Vector(); result = new Integer(cpool.length + MoreStuff.size()); MoreStuff.addElement(string); indexHashAscii.put(string, result); } return result.intValue(); } /** * Create a hash table of all the items in the constant pool that could * possibly be referenced from the outside. */ public void createIndexHash(Environment env) { indexHashObject = new Hashtable(); indexHashAscii = new Hashtable(); for (int i = 1; i < cpool.length; i++) { if (types[i] == CONSTANT_UTF8) { indexHashAscii.put(cpool[i], new Integer(i)); } else { try { indexHashObject.put(getConstant(i, env), new Integer(i)); } catch (ClassFormatError e) { } } } } /** * Write out the contents of the constant pool, including any additions * that have been added. */ public void write(DataOutputStream out, Environment env) throws IOException { int length = cpool.length; if (MoreStuff != null) length += MoreStuff.size(); out.writeShort(length); for (int i = 1 ; i < cpool.length; i++) { int type = types[i]; Object x = cpool[i]; out.writeByte(type); switch (type) { case CONSTANT_UTF8: out.writeUTF((String) x); break; case CONSTANT_INTEGER: out.writeInt(((Number)x).intValue()); break; case CONSTANT_FLOAT: out.writeFloat(((Number)x).floatValue()); break; case CONSTANT_LONG: out.writeLong(((Number)x).longValue()); i++; break; case CONSTANT_DOUBLE: out.writeDouble(((Number)x).doubleValue()); i++; break; case CONSTANT_CLASS: case CONSTANT_STRING: out.writeShort(((Number)x).intValue()); break; case CONSTANT_FIELD: case CONSTANT_METHOD: case CONSTANT_INTERFACEMETHOD: case CONSTANT_NAMEANDTYPE: { int value = ((Number)x).intValue(); out.writeShort(value >> 16); out.writeShort(value & 0xFFFF); break; } default: throw new ClassFormatError("invalid constant type: " + (int)types[i]); } } for (int i = cpool.length; i < length; i++) { String string = (String)(MoreStuff.elementAt(i - cpool.length)); out.writeByte(CONSTANT_UTF8); out.writeUTF(string); } }}
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.Vector;
import java.util.Hashtable;
/**
* This class is used to represent a constant table once
* it is read from a class file.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public final
class BinaryConstantPool implements Constants {
private byte types[];
private Object cpool[];
/**
* Constructor
*/
BinaryConstantPool(DataInputStream in) throws IOException {
// JVM 4.1 ClassFile.constant_pool_count
types = new byte[in.readUnsignedShort()];
cpool = new Object[types.length];
for (int i = 1 ; i < cpool.length ; i++) {
int j = i;
// JVM 4.4 cp_info.tag
switch(types[i] = in.readByte()) {
case CONSTANT_UTF8:
cpool[i] = in.readUTF();
break;
case CONSTANT_INTEGER:
cpool[i] = new Integer(in.readInt());
break;
case CONSTANT_FLOAT:
cpool[i] = new Float(in.readFloat());
break;
case CONSTANT_LONG:
cpool[i++] = new Long(in.readLong());
break;
case CONSTANT_DOUBLE:
cpool[i++] = new Double(in.readDouble());
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
// JVM 4.4.3 CONSTANT_String_info.string_index
// or JVM 4.4.1 CONSTANT_Class_info.name_index
cpool[i] = new Integer(in.readUnsignedShort());
break;
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
case CONSTANT_NAMEANDTYPE:
// JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort());
break;
case 0:
default:
throw new ClassFormatError("invalid constant type: " + (int)types[i]);
}
}
}
/**
* get a integer
*/
public int getInteger(int n) {
return (n == 0) ? 0 : ((Number)cpool[n]).intValue();
}
/**
* get a value
*/
public Object getValue(int n) {
return (n == 0) ? null : cpool[n];
}
/**
* get a string
*/
public String getString(int n) {
return (n == 0) ? null : (String)cpool[n];
}
/**
* get an identifier
*/
public Identifier getIdentifier(int n) {
return (n == 0) ? null : Identifier.lookup(getString(n));
}
/**
* get class declaration
*/
public ClassDeclaration getDeclarationFromName(Environment env, int n) {
return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.')));
}
/**
* get class declaration
*/
public ClassDeclaration getDeclaration(Environment env, int n) {
return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));
}
/**
* get a type from a type signature
*/
public Type getType(int n) {
return Type.tType(getString(n));
}
/**
* get the type of constant given an index
*/
public int getConstantType(int n) {
return types[n];
}
/**
* get the n-th constant from the constant pool
*/
public Object getConstant(int n, Environment env) {
int constant_type = getConstantType(n);
switch (constant_type) {
case CONSTANT_INTEGER:
case CONSTANT_FLOAT:
case CONSTANT_LONG:
case CONSTANT_DOUBLE:
return getValue(n);
case CONSTANT_CLASS:
return getDeclaration(env, n);
case CONSTANT_STRING:
return getString(getInteger(n));
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
try {
int key = getInteger(n);
ClassDefinition clazz =
getDeclaration(env, key >> 16).getClassDefinition(env);
int name_and_type = getInteger(key & 0xFFFF);
Identifier id = getIdentifier(name_and_type >> 16);
Type type = getType(name_and_type & 0xFFFF);
for (MemberDefinition field = clazz.getFirstMatch(id);
field != null;
field = field.getNextMatch()) {
Type field_type = field.getType();
if ((constant_type == CONSTANT_FIELD)
? (field_type == type)
: (field_type.equalArguments(type)))
return field;
}
} catch (ClassNotFound e) {
}
return null;
default:
throw new ClassFormatError("invalid constant type: " +
constant_type);
}
}
/**
* Get a list of dependencies, ie: all the classes referenced in this
* constant pool.
*/
public Vector getDependencies(Environment env) {
Vector v = new Vector();
for (int i = 1 ; i < cpool.length ; i++) {
switch(types[i]) {
case CONSTANT_CLASS:
v.addElement(getDeclarationFromName(env, getInteger(i)));
break;
}
}
return v;
}
Hashtable indexHashObject, indexHashAscii;
Vector MoreStuff;
/**
* Find the index of an Object in the constant pool
*/
public int indexObject(Object obj, Environment env) {
if (indexHashObject == null)
createIndexHash(env);
Integer result = (Integer)indexHashObject.get(obj);
if (result == null)
throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " +
obj.getClass() + " in constant pool");
return result.intValue();
}
/**
* Find the index of an ascii string in the constant pool. If it's not in
* the constant pool, then add it at the end.
*/
public int indexString(String string, Environment env) {
if (indexHashObject == null)
createIndexHash(env);
Integer result = (Integer)indexHashAscii.get(string);
if (result == null) {
if (MoreStuff == null) MoreStuff = new Vector();
result = new Integer(cpool.length + MoreStuff.size());
MoreStuff.addElement(string);
indexHashAscii.put(string, result);
}
return result.intValue();
}
/**
* Create a hash table of all the items in the constant pool that could
* possibly be referenced from the outside.
*/
public void createIndexHash(Environment env) {
indexHashObject = new Hashtable();
indexHashAscii = new Hashtable();
for (int i = 1; i < cpool.length; i++) {
if (types[i] == CONSTANT_UTF8) {
indexHashAscii.put(cpool[i], new Integer(i));
} else {
try {
indexHashObject.put(getConstant(i, env), new Integer(i));
} catch (ClassFormatError e) { }
}
}
}
/**
* Write out the contents of the constant pool, including any additions
* that have been added.
*/
public void write(DataOutputStream out, Environment env) throws IOException {
int length = cpool.length;
if (MoreStuff != null)
length += MoreStuff.size();
out.writeShort(length);
for (int i = 1 ; i < cpool.length; i++) {
int type = types[i];
Object x = cpool[i];
out.writeByte(type);
switch (type) {
case CONSTANT_UTF8:
out.writeUTF((String) x);
break;
case CONSTANT_INTEGER:
out.writeInt(((Number)x).intValue());
break;
case CONSTANT_FLOAT:
out.writeFloat(((Number)x).floatValue());
break;
case CONSTANT_LONG:
out.writeLong(((Number)x).longValue());
i++;
break;
case CONSTANT_DOUBLE:
out.writeDouble(((Number)x).doubleValue());
i++;
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
out.writeShort(((Number)x).intValue());
break;
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
case CONSTANT_NAMEANDTYPE: {
int value = ((Number)x).intValue();
out.writeShort(value >> 16);
out.writeShort(value & 0xFFFF);
break;
}
default:
throw new ClassFormatError("invalid constant type: "
+ (int)types[i]);
}
}
for (int i = cpool.length; i < length; i++) {
String string = (String)(MoreStuff.elementAt(i - cpool.length));
out.writeByte(CONSTANT_UTF8);
out.writeUTF(string);
}
}
}