public void writeBytes(OutputStream os) throws IOException { // Map between any modified UTF-8 and it's constant pool index. Map utf8ToIndex = new HashMap(); DataOutputStream dos = new DataOutputStream(os); TypeArray tags = getTags(); int len = (int) getLength(); int ci = 0; // constant pool index // collect all modified UTF-8 Strings from Constant Pool for (ci = 1; ci < len; ci++) { byte cpConstType = tags.getByteAt(ci); if (cpConstType == JVM_CONSTANT_Utf8) { Symbol sym = getSymbolAt(ci); utf8ToIndex.put(sym.asString(), new Short((short) ci)); } else if (cpConstType == JVM_CONSTANT_Long || cpConstType == JVM_CONSTANT_Double) { ci++; } } for (ci = 1; ci < len; ci++) { int cpConstType = (int) tags.getByteAt(ci); // write cp_info // write constant type switch (cpConstType) { case JVM_CONSTANT_Utf8: { dos.writeByte(cpConstType); Symbol sym = getSymbolAt(ci); dos.writeShort((short) sym.getLength()); dos.write(sym.asByteArray()); if (DEBUG) debugMessage("CP[" + ci + "] = modified UTF-8 " + sym.asString()); break; } case JVM_CONSTANT_Unicode: throw new IllegalArgumentException("Unicode constant!"); case JVM_CONSTANT_Integer: dos.writeByte(cpConstType); dos.writeInt(getIntAt(ci)); if (DEBUG) debugMessage("CP[" + ci + "] = int " + getIntAt(ci)); break; case JVM_CONSTANT_Float: dos.writeByte(cpConstType); dos.writeFloat(getFloatAt(ci)); if (DEBUG) debugMessage("CP[" + ci + "] = float " + getFloatAt(ci)); break; case JVM_CONSTANT_Long: { dos.writeByte(cpConstType); long l = getLongAt(ci); // long entries occupy two pool entries ci++; dos.writeLong(l); break; } case JVM_CONSTANT_Double: dos.writeByte(cpConstType); dos.writeDouble(getDoubleAt(ci)); // double entries occupy two pool entries ci++; break; case JVM_CONSTANT_Class: { dos.writeByte(cpConstType); // Klass already resolved. ConstantPool constains klassOop. Klass refKls = (Klass) getObjAt(ci); String klassName = refKls.getName().asString(); Short s = (Short) utf8ToIndex.get(klassName); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); break; } // case JVM_CONSTANT_ClassIndex: case JVM_CONSTANT_UnresolvedClass: { dos.writeByte(JVM_CONSTANT_Class); String klassName = getSymbolAt(ci).asString(); Short s = (Short) utf8ToIndex.get(klassName); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = class " + s); break; } case JVM_CONSTANT_String: { dos.writeByte(cpConstType); String str = OopUtilities.stringOopToString(getObjAt(ci)); Short s = (Short) utf8ToIndex.get(str); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); break; } // case JVM_CONSTANT_StringIndex: case JVM_CONSTANT_UnresolvedString: { dos.writeByte(JVM_CONSTANT_String); String val = getSymbolAt(ci).asString(); Short s = (Short) utf8ToIndex.get(val); dos.writeShort(s.shortValue()); if (DEBUG) debugMessage("CP[" + ci + "] = string " + s); break; } // all external, internal method/field references case JVM_CONSTANT_Fieldref: case JVM_CONSTANT_Methodref: case JVM_CONSTANT_InterfaceMethodref: { dos.writeByte(cpConstType); int value = getIntAt(ci); short klassIndex = (short) extractLowShortFromInt(value); short nameAndTypeIndex = (short) extractHighShortFromInt(value); dos.writeShort(klassIndex); dos.writeShort(nameAndTypeIndex); if (DEBUG) debugMessage( "CP[" + ci + "] = ref klass = " + klassIndex + ", N&T = " + nameAndTypeIndex); break; } case JVM_CONSTANT_NameAndType: { dos.writeByte(cpConstType); int value = getIntAt(ci); short nameIndex = (short) extractLowShortFromInt(value); short signatureIndex = (short) extractHighShortFromInt(value); dos.writeShort(nameIndex); dos.writeShort(signatureIndex); if (DEBUG) debugMessage( "CP[" + ci + "] = N&T name = " + nameIndex + ", type = " + signatureIndex); break; } } // switch } dos.flush(); return; }
private boolean isInInnerClasses(Symbol sym, boolean includeLocals) { TypeArray innerClassList = getInnerClasses(); int length = (innerClassList == null) ? 0 : (int) innerClassList.getLength(); if (length > 0) { if (Assert.ASSERTS_ENABLED) { Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking"); } for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) { int ioff = innerClassList.getShortAt(i + InnerClassAttributeOffset.innerClassInnerClassInfoOffset); // 'ioff' can be zero. // refer to JVM spec. section 4.7.5. if (ioff != 0) { Oop iclassInfo = getConstants().getObjAt(ioff); Symbol innerName = null; if (iclassInfo instanceof Klass) { innerName = ((Klass) iclassInfo).getName(); } else if (iclassInfo instanceof Symbol) { innerName = (Symbol) iclassInfo; } else { throw new RuntimeException("should not reach here"); } Symbol myname = getName(); int ooff = innerClassList.getShortAt( i + InnerClassAttributeOffset.innerClassOuterClassInfoOffset); // for anonymous classes inner_name_index of InnerClasses // attribute is zero. int innerNameIndex = innerClassList.getShortAt(i + InnerClassAttributeOffset.innerClassInnerNameOffset); // if this is not a member (anonymous, local etc.), 'ooff' will be zero // refer to JVM spec. section 4.7.5. if (ooff == 0) { if (includeLocals) { // does it looks like my local class? if (innerName.equals(sym) && innerName.asString().startsWith(myname.asString())) { // exclude anonymous classes. return (innerNameIndex != 0); } } } else { Oop oclassInfo = getConstants().getObjAt(ooff); Symbol outerName = null; if (oclassInfo instanceof Klass) { outerName = ((Klass) oclassInfo).getName(); } else if (oclassInfo instanceof Symbol) { outerName = (Symbol) oclassInfo; } else { throw new RuntimeException("should not reach here"); } // include only if current class is outer class. if (outerName.equals(myname) && innerName.equals(sym)) { return true; } } } } // for inner classes return false; } else { return false; } }