Question

I've been trying to search around web for guides/help for accessing byte code classes via interface that the byte code class is casted to in ASM. I've seen this done on RuneScape bot called powerbot (RSBot) which source I also got from https://github.com/powerbot/RSBot but i cannot understand how is it done as I get class cast exception when casting a class to interface which contains the "skeleton" of every method.. I know it must be stupid to think like you could just cast a class to interface.. I know there must be some preparements or so but in ASM book/ebook (http://download.forge.objectweb.org/asm/asm-guide.pdf) theres nothing about it as far as i've readed. I am really interested in this, not to make a new RS bot but to learn this cool library to replace BCEL in my needs. I'll give you a quick example to understand this problem better!

Here i have class called "helloSO"

public class helloSO {

    public void doSomething(){
        System.out.println("I did something! :D");
    }

}

and here i have interface called "helloSO" also

public interface helloSO {

    public void doSomething();

}

i would like to be able to cast the .class i read and define to class with ASM to that interface to be able to call the methods from that instance with their names.. I hope i explained this well enought. If you want you can check the RSBot to see better what i mean. :) So what i am asking is; what preparations I have to do and where can i learn about them? I am not asking you to create me class adapter or anything just advice and help :) Thanks in advance!

Was it helpful?

Solution

Adding an interface using a ClassAdapter is actually pretty simple if your class already contains a matching method. You just have to override the visit method which gets passed an array of interface names and add another interface before delegating to the super implementation:

@Override
public void visit(final int version, final int access, final String classname, final String signature, final String superName, final String[] interfaces) {
    Set<String> newinterfaces = new HashSet<String>(Arrays.asList(interfaces));
    newinterfaces.add(helloSO.class.getName().replace('.', '/'));
    super.visit(version, access, classname, signature, superName, newinterfaces.toArray(new String[newinterfaces.size()]));
}

I'm using a Set here for the interfaces in case the class already implements the new interface. The interfaces are named using their internal names, which just means that dots in the package name get replaced by slashes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top