How can I change the class name from the main method?
Closed due to the fact that the essence of the question is incomprehensible by the participants Roman C , Anton Sorokin , Suvitruf
Try to write more detailed questions. To get an answer, explain what exactly you see the problem, how to reproduce it, what you want to get as a result, etc. Give an example that clearly demonstrates the problem. If the question can be reformulated according to the rules set out in the certificate , edit it .
- incomprehensible what it is about .. - keekkenen
2 answers
Yes, you do not listen to them, you can, of course, you can, and even in runtime, but is the game worth the candle? (: And not to be vocal - project and tutorial ; not on the subject matter, but on the library guide . But even a working (almost) example. Changes your Date
to DateInsane
, and loads all private methods public. True debug, something else is fun.
private Class<?> magicTransform(Class clazz, List<String> list, boolean fillInnerClasses) { String defineName = clazz.getName().concat("Insane"); String className = clazz.getName().replace(".", "/"); String defineClassName = defineName.replace(".", "/"); class AssertorMethodAdapter extends ClassVisitor { private AssertorMethodAdapter(ClassVisitor cv) { super(ASM4, cv); this.cv = cv; } private String replaceIfContains(String s) { return replaceIfContains(s, className, defineClassName); } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, access, replaceIfContains(name), signature, superName, interfaces); } @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { super.visitInnerClass(replaceIfContains(name), replaceIfContains(outerName), innerName, access); } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { return super.visitField(access, name, replaceIfContains(desc), signature, value); } @Override public void visitAttribute(Attribute attr) { super.visitAttribute(attr); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mvno = new MethodVisitor(ASM5, cv.visitMethod( list.contains(name) ? (access == ACC_PRIVATE ? ACC_PUBLIC : access) : access, name, replaceIfContains(desc), replaceIfContains(signature), exceptions)) { @Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { for (int i = 0; i < bsmArgs.length; i++) { if (bsmArgs[i] instanceof String) { bsmArgs[i] = replaceIfContains(((String) bsmArgs[i])); } } super.visitInvokeDynamicInsn(name, replaceIfContains(desc), new Handle(bsm.getTag(), replaceIfContains(bsm.getOwner()), replaceIfContains(bsm.getName()), replaceIfContains(bsm.getDesc()), bsm.isInterface()), bsmArgs); } @Override public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { super.visitLocalVariable(name, replaceIfContains(desc), replaceIfContains(signature), start, end, index); } @Override public void visitLdcInsn(Object cst) { if (Type.getDescriptor(clazz).equals(cst.toString())) { super.visitLdcInsn(Type.getObjectType(defineClassName)); } else { super.visitLdcInsn(cst); } } @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { super.visitFieldInsn(opcode, replaceIfContains(owner), name, replaceIfContains(desc)); } @Override public void visitParameter(String name, int access) { super.visitParameter(replaceIfContains(name), access); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { super.visitMethodInsn(opcode, replaceIfContains(owner), name, replaceIfContains(desc), itf); } @Override public void visitTypeInsn(int opcode, String type) { super.visitTypeInsn(opcode, replaceIfContains(type)); } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return super.visitAnnotation(desc, visible); } @Override public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) { for (int i = 0; i < local.length; i++) { if (local[i] instanceof String) { local[i] = replaceIfContains(((String) local[i])); } } super.visitFrame(type, nLocal, local, nStack, stack); } }; return mvno; } } try { ClassReader reader = new ClassReader(clazz.getName()); ClassWriter writer = new ClassWriter(reader, 0); AssertorMethodAdapter adapter = new AssertorMethodAdapter(writer); reader.accept(adapter, 0); byte[] bytes = writer.toByteArray(); Method defineClass = PluginsUtil.getPrivateMethod(ClassLoader.class, "defineClass", new Class[]{String.class, byte[].class, int.class, int.class}); defineClass.invoke(clazz.getClassLoader(), defineName, bytes, 0, bytes.length); if (fillInnerClasses) { ClassNode cn = new ClassNode(); reader.accept(cn, 0); Map<String, byte[]> innerClasses = cn.innerClasses.stream() .filter(innerClassNode -> innerClassNode.name.contains(className)).collect(Collectors.toMap( (innerClassNode) -> replaceIfContains(innerClassNode.name, className, defineClassName), innerClassNode -> { try { ClassReader r = new ClassReader(innerClassNode.name); ClassWriter w = new ClassWriter(r, 0); AssertorMethodAdapter a = new AssertorMethodAdapter(w); r.accept(a, 0); return w.toByteArray(); } catch (IOException e) { e.printStackTrace(); return new byte[0]; } })); innerClasses.forEach((name, bytes1) -> { try { defineClass.invoke(clazz.getClassLoader(), name.replace("/", "."), bytes1, 0, bytes1.length); } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } }); } return clazz.getClassLoader().loadClass(defineName); } catch (IOException | IllegalAccessException | InvocationTargetException | ClassNotFoundException e) { e.printStackTrace(); } return clazz; } private String replaceIfContains(String s, String containString, String replaceString) { if (s == null) { return null; } return s.contains(containString) ? s.replace(containString, replaceString) : s; }
No After you have written a class (for example, Data
) and compiled a program, the class name cannot be changed. Data
will always be Data
. I believe that whatever problem you currently have, it can be solved differently, without changing the name of the class.
- Doesn't Refactor -> Rename change the class name in the entire project in IntelJ Idea? - danilshik 3:18 pm
- @danilshik is an operation on the source code, it has nothing to do with runtime. - Sergey Gornostaev