mirror of
https://github.com/tiennm99/lombok.git
synced 2026-10-13 20:15:09 +00:00
Fixed some bugs in reading the constant pool and added tests
This commit is contained in:
1 parent
b14eef7eed
commit
2683c24ee9
3 files changed
+199
-10
No files matched your search
@@ -40,6 +40,7 @@ public class ClassFileMetaData {
|
||||
private static final byte NAME_TYPE = 12;
|
||||
|
||||
private static final int NOT_FOUND = -1;
|
||||
private static final int START_OF_CONSTANT_POOL = 8;
|
||||
|
||||
private final byte[] byteCode;
|
||||
|
||||
@@ -52,12 +53,12 @@ public class ClassFileMetaData {
|
||||
public ClassFileMetaData(byte[] byteCode) {
|
||||
this.byteCode = byteCode;
|
||||
|
||||
maxPoolSize = readValue(8) + 1;
|
||||
maxPoolSize = readValue(START_OF_CONSTANT_POOL);
|
||||
offsets = new int[maxPoolSize];
|
||||
types = new byte[maxPoolSize];
|
||||
utf8s = new String[maxPoolSize];
|
||||
int position = 10;
|
||||
for (int i = 1; i < maxPoolSize - 1; i++) {
|
||||
for (int i = 1; i < maxPoolSize; i++) {
|
||||
byte type = byteCode[position];
|
||||
types[i] = type;
|
||||
position++;
|
||||
@@ -84,6 +85,7 @@ public class ClassFileMetaData {
|
||||
case LONG:
|
||||
case DOUBLE:
|
||||
position += 8;
|
||||
i++;
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
@@ -178,6 +180,65 @@ public class ClassFileMetaData {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsLong(long value) {
|
||||
for (int i = 1; i < maxPoolSize; i++) {
|
||||
if (types[i] == LONG && readLong(i) == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsDouble(double value) {
|
||||
boolean isNan = Double.isNaN(value);
|
||||
for (int i = 1; i < maxPoolSize; i++) {
|
||||
if (types[i] == DOUBLE) {
|
||||
double d = readDouble(i);
|
||||
if (d == value || (isNan && Double.isNaN(d))) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsInteger(int value) {
|
||||
for (int i = 1; i < maxPoolSize; i++) {
|
||||
if (types[i] == INTEGER && readInteger(i) == value) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsFloat(float value) {
|
||||
boolean isNan = Float.isNaN(value);
|
||||
for (int i = 1; i < maxPoolSize; i++) {
|
||||
if (types[i] == FLOAT) {
|
||||
float f = readFloat(i);
|
||||
if (f == value || (isNan && Float.isNaN(f))) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private long readLong(int index) {
|
||||
int pos = offsets[index];
|
||||
return ((long)read32(pos)) << 32 | read32(pos + 4);
|
||||
}
|
||||
|
||||
private double readDouble(int index) {
|
||||
int pos = offsets[index];
|
||||
long bits = ((long)read32(pos)) << 32 | (read32(pos + 4) & 0x00000000FFFFFFFF);
|
||||
return Double.longBitsToDouble(bits);
|
||||
}
|
||||
|
||||
private long readInteger(int index) {
|
||||
return read32(offsets[index]);
|
||||
}
|
||||
|
||||
private float readFloat(int index) {
|
||||
return Float.intBitsToFloat(read32(offsets[index]));
|
||||
}
|
||||
|
||||
private int read32(int pos) {
|
||||
return (byteCode[pos] & 0xFF) << 24 | (byteCode[pos + 1] & 0xFF) << 16 | (byteCode[pos + 2] & 0xFF) << 8 | (byteCode[pos + 3] &0xFF);
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return getClassName(readValue(endOfPool + 2));
|
||||
}
|
||||
@@ -197,6 +258,63 @@ public class ClassFileMetaData {
|
||||
return result;
|
||||
}
|
||||
|
||||
public String poolContent() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 1; i < maxPoolSize; i++) {
|
||||
result.append(String.format("#%02d: ", i));
|
||||
int pos = offsets[i];
|
||||
switch(types[i]) {
|
||||
case UTF8:
|
||||
result.append("Utf8 ").append(utf8s[i]);
|
||||
break;
|
||||
case CLASS:
|
||||
result.append("Class ").append(getClassName(i));
|
||||
break;
|
||||
case STRING:
|
||||
result.append("String \"").append(utf8s[readValue(pos)]).append("\"");
|
||||
break;
|
||||
case INTEGER:
|
||||
result.append("int ").append(readInteger(i));
|
||||
break;
|
||||
case FLOAT:
|
||||
result.append("float ").append(readFloat(i));
|
||||
break;
|
||||
case FIELD:
|
||||
appendAccess(result.append("Field "), i);
|
||||
break;
|
||||
case METHOD:
|
||||
case IMETHOD:
|
||||
appendAccess(result.append("Method "), i);
|
||||
break;
|
||||
case NAME_TYPE:
|
||||
appendNameAndType(result.append("Name&Type "), i);
|
||||
break;
|
||||
case LONG:
|
||||
result.append("long ").append(readLong(i));
|
||||
break;
|
||||
case DOUBLE:
|
||||
result.append("double ").append(readDouble(i));
|
||||
break;
|
||||
case 0:
|
||||
result.append("(cont.)");
|
||||
break;
|
||||
}
|
||||
result.append("\n");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void appendAccess(StringBuilder result, int index) {
|
||||
int pos = offsets[index];
|
||||
result.append(getClassName(readValue(pos))).append(".");
|
||||
appendNameAndType(result, readValue(pos + 2));
|
||||
}
|
||||
|
||||
private void appendNameAndType(StringBuilder result, int index) {
|
||||
int pos = offsets[index];
|
||||
result.append(utf8s[readValue(pos)]).append(":").append(utf8s[readValue(pos + 2)]);
|
||||
}
|
||||
|
||||
private String getClassName(int classIndex) {
|
||||
if (classIndex < 1) return null;
|
||||
return utf8s[readValue(offsets[classIndex])];
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
public class Foo implements java.util.RandomAccess {
|
||||
private static final long LONG = 123L;
|
||||
private static final String ONE = "Eén";
|
||||
private static final int INT = 123;
|
||||
private static final double DOUBLE = 1.23;
|
||||
private static final double DOUBLE_NAN = Double.NaN;
|
||||
private static final double DOUBLE_INF = Double.POSITIVE_INFINITY;
|
||||
private static final double DOUBLE_NEG_INF = Double.NEGATIVE_INFINITY;
|
||||
|
||||
private static final float FLOAT = 1.23F;
|
||||
private static final float FLOAT_NAN = Float.NaN;
|
||||
private static final float FLOAT_INF = Float.POSITIVE_INFINITY;
|
||||
private static final float FLOAT_NEG_INF = Float.NEGATIVE_INFINITY;
|
||||
|
||||
{
|
||||
String value = toString();
|
||||
|
||||
@@ -43,10 +43,24 @@ import org.junit.Test;
|
||||
|
||||
public class ClassFileMetaDataTest {
|
||||
|
||||
private ClassFileMetaData foo = create(new File("test/bytecode/resource/Foo.java"));
|
||||
private ClassFileMetaData bar = create(new File("test/bytecode/resource/Bar.java"));
|
||||
private ClassFileMetaData baz = create(new File("test/bytecode/resource/Baz.java"));
|
||||
private ClassFileMetaData buux = create(new File("test/bytecode/resource/Buux.java"));
|
||||
private static ClassFileMetaData foo = create(new File("test/bytecode/resource/Foo.java"));
|
||||
private static ClassFileMetaData bar = create(new File("test/bytecode/resource/Bar.java"));
|
||||
private static ClassFileMetaData baz = create(new File("test/bytecode/resource/Baz.java"));
|
||||
private static ClassFileMetaData buux = create(new File("test/bytecode/resource/Buux.java"));
|
||||
|
||||
// @Test
|
||||
// public void dump() {
|
||||
// byte[] bytes = compile(new File("test/bytecode/resource/Foo.java"));
|
||||
// int count = 0;
|
||||
// for (byte b : bytes) {
|
||||
// System.out.printf("%02x ", (b & 0xFF));
|
||||
// count++;
|
||||
// if (count % 20 == 0) System.out.println();
|
||||
// }
|
||||
// System.out.println();
|
||||
// System.out.println();
|
||||
// System.out.println(foo.poolContent());
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testGetClassName() {
|
||||
@@ -125,13 +139,59 @@ public class ClassFileMetaDataTest {
|
||||
assertTrue(foo.containsStringConstant("TwoFour"));
|
||||
|
||||
assertTrue(buux.containsStringConstant("H\u3404l\0"));
|
||||
|
||||
assertFalse(foo.containsStringConstant("Seven"));
|
||||
}
|
||||
|
||||
private ClassFileMetaData create(File file) {
|
||||
@Test
|
||||
public void testContainsDouble() {
|
||||
assertTrue(foo.containsDouble(1.23));
|
||||
assertTrue(foo.containsDouble(Double.NaN));
|
||||
assertTrue(foo.containsDouble(Double.POSITIVE_INFINITY));
|
||||
assertTrue(foo.containsDouble(Double.NEGATIVE_INFINITY));
|
||||
|
||||
assertFalse(foo.containsDouble(1.0));
|
||||
assertFalse(buux.containsDouble(1.0));
|
||||
assertFalse(buux.containsDouble(Double.NaN));
|
||||
assertFalse(buux.containsDouble(Double.POSITIVE_INFINITY));
|
||||
assertFalse(buux.containsDouble(Double.NEGATIVE_INFINITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsFloat() {
|
||||
assertTrue(foo.containsFloat(1.23F));
|
||||
assertTrue(foo.containsFloat(Float.NaN));
|
||||
assertTrue(foo.containsFloat(Float.POSITIVE_INFINITY));
|
||||
assertTrue(foo.containsFloat(Float.NEGATIVE_INFINITY));
|
||||
|
||||
assertFalse(foo.containsFloat(1.0F));
|
||||
assertFalse(buux.containsFloat(1.0F));
|
||||
assertFalse(buux.containsFloat(Float.NaN));
|
||||
assertFalse(buux.containsFloat(Float.POSITIVE_INFINITY));
|
||||
assertFalse(buux.containsFloat(Float.NEGATIVE_INFINITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsInteger() {
|
||||
assertTrue(foo.containsInteger(123));
|
||||
|
||||
assertFalse(foo.containsInteger(1));
|
||||
assertFalse(buux.containsInteger(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsLong() {
|
||||
assertTrue(foo.containsLong(123));
|
||||
|
||||
assertFalse(foo.containsLong(1));
|
||||
assertFalse(buux.containsLong(1));
|
||||
}
|
||||
|
||||
private static ClassFileMetaData create(File file) {
|
||||
return new ClassFileMetaData(compile(file));
|
||||
}
|
||||
|
||||
private byte[] compile(File file) {
|
||||
private static byte[] compile(File file) {
|
||||
try {
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
File tempDir = getTempDir();
|
||||
@@ -146,7 +206,7 @@ public class ClassFileMetaDataTest {
|
||||
}
|
||||
}
|
||||
|
||||
private File getTempDir() {
|
||||
private static File getTempDir() {
|
||||
String[] rawDirs = {
|
||||
System.getProperty("java.io.tmpdir"),
|
||||
"/tmp",
|
||||
@@ -177,7 +237,7 @@ public class ClassFileMetaDataTest {
|
||||
}
|
||||
}
|
||||
|
||||
private String readFileAsString(File file) {
|
||||
private static String readFileAsString(File file) {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
StringWriter writer = new StringWriter();
|
||||
|
||||
Reference in new issue
Block a user