简体   繁体   中英

Custom Classloader And Java Agent

I want to modifly the class in app which is running. So I use java agent to do this. My java code like this:

    /**
 * 
 * @param args
 * @param inst
 */
public static void agentmain(String args, Instrumentation inst) {
    try {
        inst.addTransformer(new GameClassFileTransformer(), true);
        parseFiles();
        List<Class<?>> retransformClasses = new ArrayList<>();
        for (JarClassInfo jarClassInfo : GameAgentMain.bugFiles.values()) {
            retransformClasses.add(Class.forName(jarClassInfo.getClassName()));
        }
        Class<?>[] classes = new Class[retransformClasses.size()];
        retransformClasses.toArray(classes);
        inst.retransformClasses(classes);
    } catch (Exception e) {
        LogUtil.error(e);
    }
}

The JarClassInfo is a class about the class I want to reload.There hava two fields in JarClassInfo ,first is className,second is bytecode(java type is byte[]),The classname is which class want to reload.But the class is loaded by

custom classLoad

.When the app run at :

retransformClasses.add(Class.forName(jarClassInfo.getClassName()));

That is a exception be thrown:

Exception in thread "Attach Listener" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:382)
        at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:407)
Caused by: java.lang.ClassFormatError: Incompatible magic value 2329931675 in class file com/jingqi/game/module/chat/command/SendChatMsgCMD
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$1(URLClassLoader.java:409)
        at java.net.URLClassLoader$2.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$2.run(URLClassLoader.java:1)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:190)
        at com.jingqi.game.agent.GameAgentMain.agentmain(GameAgentMain.java:60)
        ... 6 more

My custom classloader(EncrypClassLoader) is used to decode my class. So the methd call stack indicate sun.misc.Launcher$AppClassLoader to load SendChatMsgCMD .The SendChatMsgCMD is not a normal class file(because I encrypt this class file).

So ,what method can be solved 。

Your custom classloader isn't doing what it's supposed to do: decrypt classes.
That's why you're​ getting​ the java.lang.ClassFormatError about the invalid magic value.

EDIT: you need to also realise that Class.forName() will load the class referred by the classname argument using the current class's classloader.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM