Изменение имени класса java [закрыт]

171
21 октября 2019, 15:30

Как можно изменить имя класса из главного метода?

Answer 1

Да не слушайте вы их, можно, конечно можно и даже в рантайме, только стоит ли игра свеч? (: И что бы не быть голосовым - проект и туториал; не по теме вопроса, но о библиотеке гайд. А вот даже рабочий(почти) пример. Меняет ваш Date на DateInsane, и в нагрузку все приватные методы делает публичными. Правда дебажить, то ещё удовольствие.

    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;
    }
Answer 2

Никак. После того, как вы написали класс (например Data) и скомпилировали программу, имя класса нельзя изменить. Data всегда будет Data. Я считаю, что какая бы проблема у вас в данный момент не возникла, ее можно решить по-другому, без изменения имени класса.

READ ALSO
отсутствует, не заполняется flowExecutionUrl

отсутствует, не заполняется flowExecutionUrl

Делаю приложение используя Spring MVC и Spring Web Flow, сделав некий flow я могу попасть на него используя ${flowExecutionUrl} в JSP файле, но из-за некой, невиданной...

121
Некорректная работа synchronized java

Некорректная работа synchronized java

Изучаю Герберта Шилдта Java 8 Руководство для начинающих, и вопрос в следующемСогласно книге метод synchronized обязан дать выполниться методу до завершения...

157
OpenGL ориентация

OpenGL ориентация

Каким образом можно сделать чтобы точка 0, 0 не была в низу слева, а чтобы она была вверху слева? Пробовал glOrtho(0D, 640D, 480D, 0D, 0D, 0D), но он ничего не делает

150
Можно ли сделать div такого вида? [закрыт]

Можно ли сделать div такого вида? [закрыт]

надо сделать див такого плана, и чтобы дочерние элементы были в закрашенной области, можно так сделать?

267