NoClassDefFoundError для внутреннего класса при переименовании класса с помощью ASM - PullRequest
1 голос
/ 30 марта 2020

Я пытаюсь переименовать класс с помощью ASM, прежде чем записывать его в файл JAR, который затем загружается обратно позже. Я реализовал свой реппер ASM следующим образом:

private static class MyClassRemapper extends Remapper {
    private final String className;

    public MyClassRemapper(Class cls) {
        className = cls.getCanonicalName().replace(".", "/");
    }

    @Override public String map(String internalName) {
        if (internalName.startsWith(className))
            return internalName.replace(className, "New" + className);
        return super.map(internalName);
    }
}

Все работает нормально, если я добавлю немного OuterClass. Однако если я затем добавлю внутренний класс InnerClass в OuterClass, то после перезагрузки JAR при попытке вызвать метод (с помощью отражения, если это имеет значение) в экземпляре NewOuterClass я получу ошибку:

java.lang.NoClassDefFoundError: com/.../NewOuterClass$InnerClass
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3139)
    at java.base/java.lang.Class.getMethodsRecursive(Class.java:3280)
    at java.base/java.lang.Class.getMethod0(Class.java:3266)
    at java.base/java.lang.Class.getMethod(Class.java:2063)
    at ...

Из ошибки ясно, что ASM успешно переименовывает некоторые ссылки на InnerClass, но, очевидно, не само определение класса. Я смотрел на реализацию mapInnerClassName, но я почти уверен, что мне не нужно этого делать, так как это меняет само InnerClass. У кого-нибудь есть идеи?

Редактировать : Если я изменю функцию map на;

    @Override public String map(String internalName) {
        if (internalName == className)
            return internalName.replace(className, "New" + className);
        return super.map(internalName);
    }

, чтобы переименовывать был только класс верхнего уровня, то Я сталкиваюсь с другой ошибкой, когда пытаюсь запустить конструктор внутреннего класса:

NoSuchMethodError: com.(...).OuterClass$InnerClass.<init>(Lcom/.../NewOuterClass)V

, что говорит о том, что методы внутреннего класса не могут быть правильно переименованы.

1 Ответ

1 голос
/ 03 апреля 2020

Хольгер в своем комментарии предоставил решение. Проблема заключалась в том, что я только переназначал файл класса внешнего класса. Однако внутренний класс также имеет свой собственный файл класса. Решение состоит в том, чтобы применить MyClassRemapper к этому и записать это также.

...