implemented some basic getBytes methods to create bytecode for constantpool
This commit is contained in:
parent
7968d27814
commit
c6db240f47
20 changed files with 147 additions and 71 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package nl.sander.beejava.constantpool;
|
||||
|
||||
import nl.sander.beejava.constantpool.entry.NodeConstant;
|
||||
import nl.sander.beejava.util.ByteBuf;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -22,6 +23,8 @@ public class ConstantPool {
|
|||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{};
|
||||
ByteBuf bytes = new ByteBuf();
|
||||
entries.forEach(entry -> bytes.add(entry.getBytes()));
|
||||
return bytes.toBytes();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantClass extends NodeConstant {
|
||||
private static final byte TAG = 7;
|
||||
private final ConstantUtf8 name;
|
||||
|
||||
public ConstantClass(ConstantUtf8 name) {
|
||||
|
|
@ -20,7 +21,7 @@ public class ConstantClass extends NodeConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 7;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, upperFraction(getNameIndex()), lowerFraction(getNameIndex())};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantDouble extends LeafConstant {
|
||||
private static final byte TAG = 6;
|
||||
private final double doubleVal;
|
||||
|
||||
public ConstantDouble(double doubleVal) {
|
||||
|
|
@ -8,7 +9,10 @@ public class ConstantDouble extends LeafConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 6;
|
||||
public byte[] getBytes() {
|
||||
long bits = Double.doubleToRawLongBits(doubleVal);
|
||||
return new byte[]{TAG, rshift(bits, 56), rshift(bits, 48), rshift(bits, 40), rshift(bits, 32),
|
||||
rshift(bits, 24), rshift(bits, 16), rshift(bits, 8), (byte) (bits & 0xFF)};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantDynamic extends NodeConstant {
|
||||
private static final byte TAG = 17;
|
||||
private final int bootstrapMethodIndex; // TODO
|
||||
private final ConstantNameAndType nameAndType;
|
||||
|
||||
|
|
@ -10,8 +11,8 @@ public class ConstantDynamic extends NodeConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 17;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
|
||||
public int getNameAndTypeIndex() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantFieldRef extends NodeConstant {
|
||||
private static final byte TAG = 9;
|
||||
|
||||
private final ConstantClass constantClass;
|
||||
private final ConstantNameAndType constantNameAndType;
|
||||
|
||||
|
|
@ -27,7 +29,8 @@ public class ConstantFieldRef extends NodeConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 9;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantFloat extends LeafConstant {
|
||||
private static final byte TAG = 4;
|
||||
|
||||
private final float floatVal;
|
||||
|
||||
public ConstantFloat(float floatVal) {
|
||||
|
|
@ -15,7 +17,8 @@ public class ConstantFloat extends LeafConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 4;
|
||||
public byte[] getBytes() {
|
||||
long bits = Float.floatToRawIntBits(floatVal);
|
||||
return new byte[]{TAG, (byte) (bits >>> 24), (byte) (bits >>> 16), (byte) (bits >>> 8), (byte) (bits & 0xFF)};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantInteger extends LeafConstant {
|
||||
private static final byte TAG = 3;
|
||||
|
||||
private final int intVal;
|
||||
|
||||
public ConstantInteger(int integer) {
|
||||
|
|
@ -15,7 +17,7 @@ public class ConstantInteger extends LeafConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 3;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, (byte) (intVal >>> 24), (byte) (intVal >>> 16), (byte) (intVal >>> 8), (byte) (intVal & 0xFF)};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantInterfaceMethodRef extends NodeConstant {
|
||||
private static final byte TAG = 11;
|
||||
|
||||
private final ConstantClass constantClass;
|
||||
private final ConstantNameAndType constantNameAndType;
|
||||
|
||||
|
|
@ -18,8 +20,9 @@ public class ConstantInterfaceMethodRef extends NodeConstant {
|
|||
return constantNameAndType.getIndex();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 11;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantInvokeDynamic extends NodeConstant {
|
||||
private static final byte TAG = 18;
|
||||
|
||||
private final int bootstrapMethodAttrIndex; //??
|
||||
private final ConstantNameAndType constantNameAndType;
|
||||
|
||||
|
|
@ -18,9 +20,9 @@ public class ConstantInvokeDynamic extends NodeConstant {
|
|||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 18;
|
||||
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
}
|
||||
//TODO implement later
|
||||
|
|
@ -2,6 +2,7 @@ package nl.sander.beejava.constantpool.entry;
|
|||
|
||||
public class ConstantLong extends LeafConstant {
|
||||
|
||||
private static final byte TAG = 5;
|
||||
private final long longVal;
|
||||
|
||||
public ConstantLong(long longVal) {
|
||||
|
|
@ -16,7 +17,10 @@ public class ConstantLong extends LeafConstant {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 5;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, rshift(longVal, 56), rshift(longVal, 48), rshift(longVal, 40), rshift(longVal, 32),
|
||||
rshift(longVal, 24), rshift(longVal, 16), rshift(longVal, 8), (byte) (longVal & 0xFF)};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package nl.sander.beejava.constantpool.entry;
|
|||
|
||||
//TODO implement later
|
||||
public class ConstantMethodHandle extends NodeConstant {
|
||||
private static final byte TAG = 15;
|
||||
|
||||
private final int referenceKind;
|
||||
|
||||
// only 1 of these can be present:
|
||||
|
|
@ -25,8 +27,7 @@ public class ConstantMethodHandle extends NodeConstant {
|
|||
return 0; //TODO implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 15;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantMethodRef extends NodeConstant {
|
||||
private static final byte TAG = 10;
|
||||
|
||||
private final ConstantClass constantClass;
|
||||
private final ConstantNameAndType constantNameAndType;
|
||||
|
||||
|
|
@ -18,8 +20,8 @@ public class ConstantMethodRef extends NodeConstant {
|
|||
return constantNameAndType.getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 10;
|
||||
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantMethodType extends NodeConstant {
|
||||
private static final byte TAG = 16;
|
||||
|
||||
private final ConstantUtf8 methodDescriptor;
|
||||
|
||||
public ConstantMethodType(ConstantUtf8 methodDescriptor) {
|
||||
|
|
@ -14,8 +16,8 @@ public class ConstantMethodType extends NodeConstant {
|
|||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 16;
|
||||
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package nl.sander.beejava.constantpool.entry;
|
|||
|
||||
public class ConstantModule extends NodeConstant {
|
||||
|
||||
private static final byte TAG = 19;
|
||||
|
||||
private final ConstantUtf8 nameEntry;
|
||||
|
||||
public ConstantModule(ConstantUtf8 nameEntry) {
|
||||
|
|
@ -9,8 +11,11 @@ public class ConstantModule extends NodeConstant {
|
|||
this.nameEntry = nameEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 19;
|
||||
public int getNameIndex() {
|
||||
return nameEntry.getIndex();
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, upperFraction(getNameIndex()), lowerFraction(getNameIndex())};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantNameAndType extends NodeConstant {
|
||||
private static final byte TAG = 12;
|
||||
private final ConstantUtf8 name;
|
||||
private final ConstantUtf8 type;
|
||||
private final ConstantUtf8 descriptor;
|
||||
|
||||
public ConstantNameAndType(ConstantUtf8 name, ConstantUtf8 type) {
|
||||
super(name,type);
|
||||
public ConstantNameAndType(ConstantUtf8 name, ConstantUtf8 descriptor) {
|
||||
super(name, descriptor);
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -15,20 +16,19 @@ public class ConstantNameAndType extends NodeConstant {
|
|||
return name.getIndex();
|
||||
}
|
||||
|
||||
public int getTypeIndex() {
|
||||
return type.getIndex();
|
||||
public int getDescriptorIndex() {
|
||||
return descriptor.getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NameAndTypeEntry{" +
|
||||
"nameIndex=" + getNameIndex() +
|
||||
", typeIndex=" + getTypeIndex() +
|
||||
", typeIndex=" + getDescriptorIndex() +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 12;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, upperFraction(getNameIndex()), lowerFraction(getNameIndex()), upperFraction(getDescriptorIndex()), lowerFraction(getDescriptorIndex())};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantPackage extends NodeConstant {
|
||||
private static final byte TAG = 20;
|
||||
private final ConstantUtf8 name;
|
||||
|
||||
public ConstantPackage(ConstantUtf8 name) {
|
||||
|
|
@ -12,8 +13,7 @@ public class ConstantPackage extends NodeConstant {
|
|||
return name.getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 20;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, upperFraction(getNameIndex()), lowerFraction(getNameIndex())};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
public class ConstantString extends NodeConstant {
|
||||
private static final byte TAG = 8;
|
||||
private final ConstantUtf8 utf8;
|
||||
|
||||
public ConstantString(ConstantUtf8 utf8) {
|
||||
|
|
@ -18,8 +19,7 @@ public class ConstantString extends NodeConstant {
|
|||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 8;
|
||||
public byte[] getBytes() {
|
||||
return new byte[]{TAG, upperFraction(getUtf8Index()), lowerFraction(getUtf8Index())};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package nl.sander.beejava.constantpool.entry;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ConstantUtf8 extends LeafConstant {
|
||||
private static final byte TAG = 1;
|
||||
private final String value;
|
||||
|
||||
public ConstantUtf8(String utf8) {
|
||||
|
|
@ -18,8 +21,13 @@ public class ConstantUtf8 extends LeafConstant {
|
|||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTag() {
|
||||
return 1;
|
||||
public byte[] getBytes() {
|
||||
byte[] utf8Bytes = value.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] bytes = new byte[utf8Bytes.length + 3];
|
||||
bytes[0] = TAG;
|
||||
bytes[1] = upperFraction(bytes.length);
|
||||
bytes[2] = lowerFraction(bytes.length);
|
||||
System.arraycopy(utf8Bytes, 0, bytes, 3, utf8Bytes.length);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,20 @@ public abstract class NodeConstant {
|
|||
this.children.addAll(Arrays.asList(children)); // java8 way destroys order, not desastrous, but I like to preserve it.
|
||||
}
|
||||
|
||||
/*
|
||||
* The tag that indicates the entry type in the bytecode.
|
||||
* §4.4 Table 4.4-A. Constant pool tags
|
||||
/**
|
||||
* return the bytes that end up in the class file.
|
||||
*/
|
||||
public abstract int getTag();
|
||||
public abstract byte[] getBytes();
|
||||
|
||||
/**
|
||||
* Convenience for test. The TAG is always the first byte of the getBytes array
|
||||
* see §4.4 Table 4.4-A. Constant pool tags
|
||||
*
|
||||
* @return a byte indicating the type of the constant
|
||||
*/
|
||||
byte getTag(){
|
||||
return getBytes()[0];
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
|
|
@ -32,4 +41,27 @@ public abstract class NodeConstant {
|
|||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns lower 8 bits as byte
|
||||
*
|
||||
* @param u16 is assumed to be 16 bits unsigned integer
|
||||
* @return lower 8 bits as byte
|
||||
*/
|
||||
protected byte lowerFraction(int u16) {
|
||||
return (byte) (u16 & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns upper 8 bits as byte
|
||||
*
|
||||
* @param u16 is assumed to be 16 bits unsigned integer
|
||||
* @return upper 8 bits as byte
|
||||
*/
|
||||
protected byte upperFraction(int u16) {
|
||||
return (byte) (u16 << 8);
|
||||
}
|
||||
|
||||
protected byte rshift(long bits, int positions) {
|
||||
return (byte) (bits >>> positions);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
public class TagCorrectnessTest {
|
||||
@Test
|
||||
public void testSpec() {
|
||||
assertEquals(7, classEntry().getTag());
|
||||
assertEquals(9, fieldRef().getTag());
|
||||
assertEquals(10, new ConstantMethodRef(classEntry(), nameAndType()).getTag());
|
||||
assertEquals(11, new ConstantInterfaceMethodRef(classEntry(), nameAndType()).getTag());
|
||||
assertEquals(8, new ConstantString(utf8()).getTag());
|
||||
assertEquals(1, utf8().getTag());
|
||||
assertEquals(3, new ConstantInteger(0).getTag());
|
||||
assertEquals(4, new ConstantFloat(0).getTag());
|
||||
assertEquals(5, new ConstantLong(0).getTag());
|
||||
assertEquals(6, new ConstantDouble(0).getTag());
|
||||
assertEquals(7, classEntry().getTag());
|
||||
assertEquals(8, new ConstantString(utf8()).getTag());
|
||||
assertEquals(9, fieldRef().getTag());
|
||||
assertEquals(10, new ConstantMethodRef(classEntry(), nameAndType()).getTag());
|
||||
assertEquals(11, new ConstantInterfaceMethodRef(classEntry(), nameAndType()).getTag());
|
||||
assertEquals(12, nameAndType().getTag());
|
||||
assertEquals(1, utf8().getTag());
|
||||
assertEquals(15, new ConstantMethodHandle(0).getTag()); //TODO
|
||||
assertEquals(16, new ConstantMethodType(utf8()).getTag()); //TODO
|
||||
assertEquals(17, new ConstantDynamic(0, nameAndType()).getTag()); //TODO
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue