Skip to content

Instantly share code, notes, and snippets.

@VijayKrishna
Last active March 16, 2024 22:43
Show Gist options
  • Save VijayKrishna/6160036 to your computer and use it in GitHub Desktop.
Save VijayKrishna/6160036 to your computer and use it in GitHub Desktop.
parse the Method description during java bytecode engineering using ASM; basically to find out the number of arguments being passed to the method.
public static char[] parseMethodArguments(String desc) {
String[] splitDesc = splitMethodDesc(desc);
char[] returnChars = new char[splitDesc.length];
int count = 0;
for(String type : splitDesc) {
if(type.startsWith("L") || type.startsWith("[")) {
returnChars[count] = 'L';
}
else {
if(type.length() > 1) { throw new RuntimeException(); }
returnChars[count] = type.charAt(0);
}
count += 1;
}
return returnChars;
}
public static String[] splitMethodDesc(String desc) {
int arraylen = methodArguments(desc).length;
int beginIndex = desc.indexOf('(');
int endIndex = desc.lastIndexOf(')');
if((beginIndex == -1 && endIndex != -1) || (beginIndex != -1 && endIndex == -1)) {
System.err.println(beginIndex);
System.err.println(endIndex);
throw new RuntimeException();
}
String x0;
if(beginIndex == -1 && endIndex == -1) {
x0 = desc;
}
else {
x0 = desc.substring(beginIndex + 1, endIndex);
}
Pattern pattern = Pattern.compile("\\[*L[^;]+;|\\[[ZBCSIFDJ]|[ZBCSIFDJ]"); //Regex for desc \[*L[^;]+;|\[[ZBCSIFDJ]|[ZBCSIFDJ]
Matcher matcher = pattern.matcher(x0);
String[] listMatches = new String[arraylen];
int counter = 0;
while(matcher.find()) {
listMatches[counter] = matcher.group();
counter += 1;
}
return listMatches;
}
@VijayKrishna
Copy link
Author

Most of the computation in the parseMethodArguments simply parses the method description which is a string. It replaces the type descriptors for arrays and objects with a capital L, and leaves the type descriptors for primitives as is. It returns a char[] with each element in the array roughly indicating the type of argument passed.

@thim-anneessens
Copy link

With the following regex (inspired by Vijay's) you can parse all arguments and return type descriptors. If only the arguments interest you, then simply ignore the last match :).

Pattern pattern = Pattern.compile("[L[^;]+;|[[ZBCSIFDJV]")

I quickly tested it on the following descriptor with success:
(IFDLjava/lang/String;SZ[Ljava/util/List<Ljava/lang/String;>;BJC)V
which is the descriptor for the following method:
public void getSomething(int v,float f,double d,String s, short ss,boolean b, List[] a,byte b1,long l, char c)

FYI Vijay: Thanks for your original regex (l.34), but it seems to lack support for multi-array primitive types.

Thank you for notifying me on any mistakes you may find in my approach

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment