Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8332059
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 9, 20262026-06-09T02:36:34+00:00 2026-06-09T02:36:34+00:00

I have a method of a class in a jar whose body I want

  • 0

I have a method of a class in a jar whose body I want to exchange with my own. In this case I just want to have the method print out “GOT IT” to the console and return true;

I am using the system loader to load the classes of the jar. I am using reflection to make the system classloader be able to load classes by bytecode. This part seems to be working correctly.

I am following the method replacement example found here: asm.ow2.org/current/asm-transformations.pdf.

My code is as follows:

public class Main 
{
    public static void main(String[] args) 
    {
        URL[] url = new URL[1];
        try
        {
            url[0] = new URL("file:////C://Users//emist//workspace//tmloader//bin//runtime//tmgames.jar");
            verifyValidPath(url[0]);
        }
        catch (Exception ex)
        {
            System.out.println("URL error");
        }
        Loader l = new Loader();
        l.loadobjection(url);
    }

    public static void verifyValidPath(URL url) throws FileNotFoundException
    {
        File filePath = new File(url.getFile());
        if (!filePath.exists()) 
        {
          throw new FileNotFoundException(filePath.getPath());
        }
    }
}

class Loader
{
    private static final Class[] parameters = new Class[] {URL.class};

    public static void addURL(URL u) throws IOException
    {
        URLClassLoader sysloader = (URLClassLoader)  ClassLoader.getSystemClassLoader();
        Class sysclass = URLClassLoader.class;

        try 
        {
            Method method = sysclass.getDeclaredMethod("addURL", parameters);
            method.setAccessible(true);
            method.invoke(sysloader, new Object[] {u});
        }
        catch (Throwable t) 
        {
            t.printStackTrace();
            throw new IOException("Error, could not add URL to system classloader");
        }

    }

    private Class loadClass(byte[] b, String name) 
    {
        //override classDefine (as it is protected) and define the class.
        Class clazz = null;
        try 
        {
            ClassLoader loader = ClassLoader.getSystemClassLoader();
            Class cls = Class.forName("java.lang.ClassLoader");
            java.lang.reflect.Method method =
                cls.getDeclaredMethod("defineClass", new Class[] { String.class, byte[].class, int.class, int.class });

            // protected method invocaton
            method.setAccessible(true);
            try 
            {
                Object[] args = new Object[] {name, b, new Integer(0), new Integer(b.length)};
                clazz = (Class) method.invoke(loader, args);
            }
            finally 
            {
                method.setAccessible(false);
            }
        }
        catch (Exception e) 
        {
            e.printStackTrace();
            System.exit(1);
        }
        return clazz;
    }

    public void loadobjection(URL[] myJar)
    {
        try 
        {
            Loader.addURL(myJar[0]);            
            //tmcore.game is the class that holds the main method in the jar
            /*
            Class<?> classToLoad = Class.forName("tmcore.game", true, this.getClass().getClassLoader());
            if(classToLoad == null)
            {
                System.out.println("No tmcore.game");
                return;
            }
            */
            MethodReplacer mr = null;

            ClassReader cr = new ClassReader("tmcore.objwin");
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
            MethodVisitor mv = null;
            try
            {
                mr = new MethodReplacer(cw, "Test", "(Ljava/lang/String;ZLjava/lang/String;)Z");
            }
            catch (Exception e)
            {
                System.out.println("Method Replacer Exception");
            }
            cr.accept(mr, ClassReader.EXPAND_FRAMES);

            PrintWriter pw = new PrintWriter(System.out);
            loadClass(cw.toByteArray(), "tmcore.objwin");
            Class<?> classToLoad = Class.forName("tmcore.game", true, this.getClass().getClassLoader());
            if(classToLoad == null)
            {
                System.out.println("No tmcore.game");
                return;
            }

            //game doesn't have a default constructor, so we need to get the reference to public game(String[] args)
            Constructor ctor = classToLoad.getDeclaredConstructor(String[].class);
            if(ctor == null)
            {
                System.out.println("can't find constructor");
                return;
            }

            //Instantiate the class by calling the constructor
            String[] args = {"tmgames.jar"};
            Object instance = ctor.newInstance(new Object[]{args});
            if(instance == null)
            {
                System.out.println("Can't instantiate constructor");
            }

            //get reference to main(String[] args)
            Method method = classToLoad.getDeclaredMethod("main", String[].class);
            //call the main method
            method.invoke(instance);

        }   
        catch (Exception ex)
        {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
        }
    }
}


public class MethodReplacer extends ClassVisitor implements Opcodes
{
    private String mname;
    private String mdesc;
    private String cname;

    public MethodReplacer(ClassVisitor cv, String mname, String mdesc)
    {
        super(Opcodes.ASM4, cv);
        this.mname = mname;
        this.mdesc = mdesc;
    }

    public void visit(int version, int access, String name, String signature, 
                      String superName, String[] interfaces)
    {
        this.cname = name;
        cv.visit(version, access, name, signature, superName, interfaces);
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                                     String[] exceptions)
    {
        String newName = name;
        if(name.equals(mname) && desc.equals(mdesc))
        {
            newName = "orig$" + name;
            generateNewBody(access, desc, signature, exceptions, name, newName);
            System.out.println("Replacing");
        }
        return super.visitMethod(access,  newName,  desc,  signature,  exceptions);
    }

    private void generateNewBody(int access, String desc, String signature, String[] exceptions,
                                String name, String newName)
    {
        MethodVisitor mv = cv.visitMethod(access,  name,  desc,  signature,  exceptions);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(access, cname, newName, desc);
        mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        mv.visitLdcInsn("GOTit!");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
        mv.visitInsn(ICONST_0);
        mv.visitInsn(IRETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
}

The problem seems to be at mv.visitMethodInsn(access, cname, newName, desc); in generateMethodBody inside MethodReplacer.

I get an “Illegal Type in constant pool” error.

I’m not sure what I’m missing…but after reading and testing for about 3 days I’m still not getting anywhere.

[Edit]

In case you were wondering, tmcore is a single player “Objection” game for lawyers. I’m doing this for the fun of it. The program successfully launches the game and everything is fine, removing the modifications from MethodReplacer makes the game behave as designed. So the issue seems to be isolated to bad bytecode/modifications by me inside the method replacer.

[EDIT2]

CheckClassAdapter.verify(cr, true, pw); returns the exact same bytecode that the function is supposed to have before editing. It is as if the changes are not being done.

[EDIT3]

copy of classtoload commented out as per comments

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-09T02:36:36+00:00Added an answer on June 9, 2026 at 2:36 am

    If you are using Eclipse, you should install Bytecode Outline – it is indispensible.

    I built a small test for what you want to achieve (this should match the signature of your test method, you will have to change package and classname):

    package checkASM;
    
    public class MethodCall {
    
        public boolean Test(String a, boolean b, String c) {
            System.out.println("GOTit");
            return false;
        }
    }
    

    requires the following bytecode to build the method:

    {
    mv = cw.visitMethod(ACC_PUBLIC, "Test",
        "(Ljava/lang/String;ZLjava/lang/String;)Z", null, null);
    mv.visitCode();
    Label l1 = new Label();
    mv.visitLabel(l1);
    mv.visitFieldInsn(GETSTATIC, "java/lang/System",
       "out", "Ljava/io/PrintStream;");
    mv.visitLdcInsn("GOTit");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream",
       "println", "(Ljava/lang/String;)V");
    Label l2 = new Label();
    mv.visitLabel(l2);
    mv.visitInsn(ICONST_0);
    mv.visitInsn(IRETURN);
    Label l3 = new Label();
    mv.visitLabel(l3);
    mv.visitLocalVariable("this", "LcheckASM/MethodCall;", null, l1, l3, 0);
    mv.visitLocalVariable("a", "Ljava/lang/String;", null, l1, l3, 1);
    mv.visitLocalVariable("b", "Z", null, l1, l3, 2);
    mv.visitLocalVariable("c", "Ljava/lang/String;", null, l1, l3, 3);
    mv.visitMaxs(4, 4);
    mv.visitEnd();
    }
    

    Calls to visitLineNumber can be omitted. So apparently, you are missing all labels, forgot to load the method parameters, did not ignore the return value, set the wrong values for visitMaxs (this is not necessarily needed, it depends on your ClassWriter flags if I recall correctly) and did not visit local variables (or parameters in this case).

    Additionally, your classloading seems to be a little confused / messed up.
    I don’t have the jar (so I can’t say if these work), but maybe you could replace Main and Loader:

    Main:

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.net.URL;
    
    public class Main {
        public static void main(String[] args) {
            try {
                Loader.instrumentTmcore(args);
            } catch (Exception e) {
                System.err.println("Ooops");
                e.printStackTrace();
            }
        }
    }
    

    Loader:

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    import java.net.URL;
    import java.net.URLClassLoader;
    
    import org.objectweb.asm.ClassReader;
    import org.objectweb.asm.ClassWriter;
    import org.objectweb.asm.MethodVisitor;
    
    public class Loader {
    
        public static ClassReader fetchReader(String binaryName) throws Exception {
            return new ClassReader(
                    Loader.class.getClassLoader().getSystemResourceAsStream(
                        binaryName.replace('.', '/') + ".class"
                    )
                )
            ;
        }
    
        public static synchronized Class<?> loadClass(byte[] bytecode)
                    throws Exception {
            ClassLoader scl = ClassLoader.getSystemClassLoader();
            Class<?>[] types = new Class<?>[] {
                    String.class, byte[].class, int.class, int.class
            };
            Object[] args = new Object[] {
                    null, bytecode, 0, bytecode.length
            };
            Method m = ClassLoader.class.getMethod("defineClass", types);
            m.setAccessible(true);
            return (Class<?>) m.invoke(scl, args);
        }
    
        public static void instrumentTmcore(String[] args) throws Exception {
            ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
            MethodReplacer mr = new MethodReplacer(cw, "Test",
                        "(Ljava/lang/String;ZLjava/lang/String;)Z");
            fetchReader("tmcore.objwin").accept(mr, ClassReader.EXPAND_FRAMES);
            loadClass(cw.toByteArray());
            Class.forName("tmcore.game")
                .getMethod("main", new Class<?>[] {args.getClass()})
                .invoke(null, new Object[] { args });
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have got my own JAR () running via separated class loaders and one
I have a method in a class in another file that I want to
I have a class that contains this class method: def self.get_event_record(row, participant) event =
I have a method in a class and a jar file is created using
I have these files board.class and x4.class (x4.class has main() method). To jar these
I have this Java class in a Jar file included as a dependency of
I have method in a class that I need to make sure is only
I have method that returns module path of given class name def findModulePath(path, className):
I have a class with a custom each-method: class CurseArray < Array def each_safe
I have a method in a class where I am triggering an error. /**

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.