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.