Re: Method Name extraction
Wojtek wrote:
This has probably been hashed to death, however,
It these a way to extract the name of the method from within that method?
The others mentioned some ways to do that. Another one is a simple 5
steps process described below:
Step 1) Design a class for a source code information retrieval.
For example:
<code>
package example;
public class CodeInfo
{
public static volatile String CLASS_NAME;
public static volatile String METHOD_NAME;
public static volatile String METHOD_DESCRIPTOR;
public static volatile String SOURCE_FILE;
public static volatile int LINE_NUMBER;
}
</code>
Step 2) Use the class designed in step 1) within your code.
Example:
<code>
package example;
import static example.CodeInfo.*;
public class CodeInfoUsage
{
public static void main(String[] args)
{
System.out.println("Hello from " + METHOD_NAME + " method of " +
CLASS_NAME + " class!");
}
}
</code>
Step 3) Compile your Java sources.
Step 4) Transform compilation results (classes) from step 3) into
desired runtime code. (Note: this step may be performed ahead of,
and/or just in runtime.)
Example class transformer based on ObjectWeb ASM 3.1:
<code>
package example;
import java.io.*;
import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;
public class CodeInfoUseTransformer
{
public static byte[] transform(byte[] bytecode)
{
ClassReader cr = new ClassReader(bytecode);
ClassWriter cw = new ClassWriter(cr, // "mostly add"
ClassWriter.COMPUTE_MAXS);
ClassVisitor cv = new ClassTransformer(cw);
cr.accept(cv, 0);
byte[] newCode = cw.toByteArray();
return newCode;
}
static final String CODE_INFO_CLASS_INTERNAL_NAME
= Type.getInternalName(CodeInfo.class);
private static class ClassTransformer extends ClassAdapter
{
String targetClassName;
String targetSourceFile;
ClassTransformer(ClassVisitor cv)
{
super(cv);
}
@Override
public void visit(
int version,
int access,
String name,
String signature,
String superName,
String[] interfaces)
{
targetClassName = name.replace('/', '.');
cv.visit(version, access, name, signature, superName, interfaces);
}
@Override
public void visitSource(String source, String debug)
{
targetSourceFile = source;
super.visitSource(source, debug);
}
@Override
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions)
{
final String targetMethodName = name;
final String targetMethodDesc = desc;
return new MethodAdapter(super.visitMethod(
access,
name,
desc,
signature,
exceptions))
{
int targetLineNumber;
@Override
public void visitLineNumber(int line, Label start)
{
targetLineNumber = line;
super.visitLineNumber(line, start);
}
@Override
public void visitFieldInsn(int opcode, String owner, String
name, String desc)
{
if (opcode == GETSTATIC &&
owner.equals(CODE_INFO_CLASS_INTERNAL_NAME))
{
if (name.equals("CLASS_NAME"))
{
super.visitLdcInsn(targetClassName);
}
else if (name.equals("METHOD_NAME"))
{
super.visitLdcInsn(targetMethodName);
}
else if (name.equals("METHOD_DESCRIPTOR"))
{
super.visitLdcInsn(targetMethodDesc);
}
else if (name.equals("SOURCE_FILE"))
{
super.visitLdcInsn(targetSourceFile);
}
else if (name.equals("LINE_NUMBER"))
{
super.visitLdcInsn(targetLineNumber);
}
else
{
super.visitFieldInsn(opcode, owner, name, desc);
}
}
else
{
super.visitFieldInsn(opcode, owner, name, desc);
}
}
};
}
}
public static void main(String[] args) throws Exception
{
if (args.length < 1 || args.length > 2)
{
System.err.println("Usage: java "
+ CodeInfoUseTransformer.class.getName()
+ " source-class-file [target-class-file]");
return;
}
File sourceFile = new File(args[0]);
File targetFile = new File(args.length == 1 ? args[0] : args[1]);
InputStream source = new FileInputStream(sourceFile);
byte[] sourceCode = new byte[(int) sourceFile.length()];
try
{
source.read(sourceCode);
}
finally
{
source.close();
}
byte[] targetCode = transform(sourceCode);
OutputStream target = new FileOutputStream(targetFile);
try
{
target.write(targetCode);
}
finally
{
target.close();
}
}
}
</code>
Step 5) Enjoy the results.
Example:
> java example.CodeInfoUsage
Hello from null method of null class!
> java example.CodeInfoUseTransformer example/CodeInfoUsage.class
> java example.CodeInfoUsage
Hello from main method of example.CodeInfoUsage class!
HTH,
piotr