mirror of
https://github.com/GTNewHorizons/GTNHLib.git
synced 2026-11-08 12:34:52 +00:00
Update the constant pool parser for Java 25 (#110)
Co-authored-by: Maya <10861407+serenibyss@users.noreply.github.com>
This commit is contained in:
1 parent
5628efe9ab
commit
192b7c86ad
2 files changed
+76
-53
No files matched your search
@@ -25,25 +25,52 @@ package com.gtnewhorizon.gtnhlib.asm;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
/**
|
||||
* Using this class to search for a (single) String reference is > 40 times faster than parsing a class with a
|
||||
* ClassReader + ClassNode while using way less RAM
|
||||
*/
|
||||
public class ClassConstantPoolParser {
|
||||
|
||||
private static final int UTF8 = 1;
|
||||
private static final int INT = 3;
|
||||
private static final int FLOAT = 4;
|
||||
private static final int LONG = 5;
|
||||
private static final int DOUBLE = 6;
|
||||
private static final int FIELD = 9;
|
||||
private static final int METH = 10;
|
||||
private static final int IMETH = 11;
|
||||
private static final int NAME_TYPE = 12;
|
||||
private static final int HANDLE = 15;
|
||||
private static final int INDY = 18;
|
||||
enum ConstantTypes {
|
||||
|
||||
INVALID, // 0 unused, if that ever changes shift this to the next unused index
|
||||
UTF8,
|
||||
// 2 unused
|
||||
INT,
|
||||
FLOAT,
|
||||
LONG,
|
||||
DOUBLE,
|
||||
CLASS_REF,
|
||||
STR_REF,
|
||||
FIELD,
|
||||
METH_REF,
|
||||
IMETH_REF,
|
||||
NAME_TYPE,
|
||||
// 13,14 unused
|
||||
METH_HANDLE,
|
||||
METH_TYPE,
|
||||
DYNAMIC,
|
||||
INVOKE_DYNAMIC,
|
||||
MODULE,
|
||||
PACKAGE;
|
||||
|
||||
// spotless:off
|
||||
// Indices in this table directly map to the values of these constants - disable spotless to make it easier to
|
||||
// see this
|
||||
static final ConstantTypes[] MAP = { INVALID,
|
||||
UTF8, INVALID, INT, FLOAT,
|
||||
LONG, DOUBLE, CLASS_REF, STR_REF,
|
||||
FIELD, METH_REF, IMETH_REF, NAME_TYPE,
|
||||
INVALID, INVALID, METH_HANDLE, METH_TYPE,
|
||||
DYNAMIC, INVOKE_DYNAMIC, MODULE, PACKAGE };
|
||||
//spotless:on
|
||||
|
||||
static ConstantTypes toType(byte code) {
|
||||
var ret = MAP[Byte.toUnsignedInt(code)];
|
||||
if (ret == INVALID) throw new RuntimeException("Invalid constant type: " + code);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[][] BYTES_TO_SEARCH;
|
||||
|
||||
@@ -78,62 +105,58 @@ public class ClassConstantPoolParser {
|
||||
if (basicClass == null || basicClass.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// checks the class version
|
||||
if (readShort(6, basicClass) > Opcodes.V1_8) {
|
||||
final var maxSupported = 69; // Java 25
|
||||
var major = readShort(6, basicClass);
|
||||
if (major > maxSupported || (major == maxSupported && readShort(4, basicClass) > 0)) {
|
||||
return false;
|
||||
}
|
||||
// parses the constant pool
|
||||
final int n = readUnsignedShort(8, basicClass);
|
||||
|
||||
// Loop through each entry in the constant pool, getting the size and content before jumping to the next.
|
||||
// Strings get scanned for the searched constants, and if found result in an early exit.
|
||||
final int numConstants = readUnsignedShort(8, basicClass);
|
||||
int index = 10;
|
||||
for (int i = 1; i < n; ++i) {
|
||||
final int size;
|
||||
switch (basicClass[index]) {
|
||||
case FIELD:
|
||||
case METH:
|
||||
case IMETH:
|
||||
case INT:
|
||||
case FLOAT:
|
||||
case NAME_TYPE:
|
||||
case INDY:
|
||||
size = 5;
|
||||
break;
|
||||
case LONG:
|
||||
case DOUBLE:
|
||||
size = 9;
|
||||
++i;
|
||||
break;
|
||||
case UTF8:
|
||||
for (int i = 1; i < numConstants; ++i) {
|
||||
int size = -1;
|
||||
|
||||
switch (ConstantTypes.toType(basicClass[index])) {
|
||||
case UTF8 -> {
|
||||
final int strLen = readUnsignedShort(index + 1, basicClass);
|
||||
size = 3 + strLen;
|
||||
|
||||
for (byte[] bytes : BYTES_TO_SEARCH) {
|
||||
if (prefixes ? strLen >= bytes.length : strLen == bytes.length) {
|
||||
boolean found = true;
|
||||
for (int j = index + 3; j < index + 3 + bytes.length; j++) {
|
||||
if (basicClass[j] != bytes[j - (index + 3)]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return true;
|
||||
if (prefixes ? strLen < bytes.length : strLen != bytes.length) continue;
|
||||
|
||||
boolean found = true;
|
||||
for (int j = index + 3; j < index + 3 + bytes.length; j++) {
|
||||
if (basicClass[j] != bytes[j - (index + 3)]) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) return true;
|
||||
}
|
||||
break;
|
||||
case HANDLE:
|
||||
size = 4;
|
||||
break;
|
||||
default:
|
||||
size = 3;
|
||||
break;
|
||||
}
|
||||
case INT, FLOAT, FIELD, METH_REF, IMETH_REF, NAME_TYPE, DYNAMIC, INVOKE_DYNAMIC -> size = 5;
|
||||
case LONG, DOUBLE -> {
|
||||
size = 9;
|
||||
++i;
|
||||
}
|
||||
case METH_HANDLE -> size = 4;
|
||||
case CLASS_REF, STR_REF, METH_TYPE, MODULE, PACKAGE -> size = 3;
|
||||
}
|
||||
|
||||
if (size < 0) throw new RuntimeException("Error parsing constant pool!");
|
||||
index += size;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static short readShort(final int index, byte[] basicClass) {
|
||||
return (short) (((basicClass[index] & 0xFF) << 8) | (basicClass[index + 1] & 0xFF));
|
||||
return (short) readUnsignedShort(index, basicClass);
|
||||
}
|
||||
|
||||
private static int readUnsignedShort(final int index, byte[] basicClass) {
|
||||
|
||||
@@ -25,7 +25,7 @@ import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
@IFMLLoadingPlugin.MCVersion("1.7.10")
|
||||
@IFMLLoadingPlugin.TransformerExclusions({ "com.gtnewhorizon.gtnhlib.core.transformer",
|
||||
@IFMLLoadingPlugin.TransformerExclusions({ "com.gtnewhorizon.gtnhlib.asm.", "com.gtnewhorizon.gtnhlib.core.transformer",
|
||||
"com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager",
|
||||
"com.gtnewhorizon.gtnhlib.client.renderer.CapturingTessellator" })
|
||||
@IFMLLoadingPlugin.SortingIndex(-1000)
|
||||
|
||||
Reference in new issue
Block a user