poco me escribió mi propio asignador ConstantPool porque ASM y JarJar tenían las siguientes cuestiones:
- para ralentizar
- no apoyó la reescritura sin todas las dependencias de clase
- no apoyó la transmisión de
- No era compatible con Remapper en modo Tree API
- Tuve que expandir y contraer StackMaps
que terminó con la siguiente:
public void process(DataInputStream in, DataOutputStream out, Function mapper) throws IOException {
int magic = in.readInt();
if (magic != 0xcafebabe) throw new ClassFormatError("wrong magic: " + magic);
out.writeInt(magic);
copy(in, out, 4); // minor and major
int size = in.readUnsignedShort();
out.writeShort(size);
for (int i = 1; i < size; i++) {
int tag = in.readUnsignedByte();
out.writeByte(tag);
Constant constant = Constant.constant(tag);
switch (constant) {
case Utf8:
out.writeUTF(mapper.apply(in.readUTF()));
break;
case Double:
case Long:
i++; // "In retrospect, making 8-byte constants take two constant pool entries was a poor choice."
// See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.5
default:
copy(in, out, constant.size);
break;
}
}
Streams.copyAndClose(in, out);
}
private final byte[] buffer = new byte[8];
private void copy(DataInputStream in, DataOutputStream out, int amount) throws IOException {
in.readFully(buffer, 0, amount);
out.write(buffer, 0, amount);
}
Y luego
public enum Constant {
Utf8(1, -1),
Integer(3, 4),
Float(4, 4),
Long(5, 8),
Double(6,8),
Class(7, 2),
String(8, 2),
Field(9, 4),
Method(10, 4),
InterfaceMethod(11, 4),
NameAndType(12, 4),
MethodHandle(15, 3),
MethodType(16, 2),
InvokeDynamic(18, 4);
public final int tag, size;
Constant(int tag, int size) { this.tag = tag; this.size = size; }
private static final Constant[] constants;
static{
constants = new Constant[19];
for (Constant c : Constant.values()) constants[c.tag] = c;
}
public static Constant constant(int tag) {
try {
Constant constant = constants[tag];
if(constant != null) return constant;
} catch (IndexOutOfBoundsException ignored) { }
throw new ClassFormatError("Unknown tag: " + tag);
}
sólo pensé que iba a presentar alternativas sin bibliotecas ya que es bastante un buen lugar para empezar a cortar a partir. Mi código está inspirado en javap código fuente
Hay un par de bibliotecas de manipulación de códigos de bytes, como ASM y BCEL, que le permiten ajustar los archivos de clase a su gusto. La mejor solución, IMO, es extraer la constante como una propiedad y pasar por el inconveniente de la recompilación el único tiempo necesario para la extracción. –
@ NathanD.Ryan Sin duda voy a extraerlo y ponerlo en un archivo de configuración para el futuro, pero en este caso específico sería muy inconveniente recompilar la versión implementada, que es bastante antigua. –
¿La cadena en cuestión es una constante en tiempo de compilación? –