Как использовать коды операций ASM.ACC_SYNTHETIC - PullRequest
1 голос
/ 05 марта 2020

Я тестирую ACC_SYNTHETIC на метод с использованием ASM. Ниже приведен мой код

    public static void generateMethodBean() throws IOException {
        System.out.println("11111");
        ClassWriter cw = new ClassWriter(0);
        cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, "cn/curious/asm/Bean", null, "java/lang/Object", null);

        MethodVisitor m0Visitor = cw.visitMethod(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, "lambda$main$1", "()V", null, null);
        m0Visitor.visitCode();
        m0Visitor.visitInsn(Opcodes.RETURN);
        m0Visitor.visitMaxs(0, 0);
        m0Visitor.visitEnd();

        cw.visitEnd();
        byte[] buffer = cw.toByteArray();
//        StringWriter stringWriter = new StringWriter();
//        PrintWriter printWriter = new PrintWriter(stringWriter);
//        CheckClassAdapter.verify(new ClassReader(buffer), true, printWriter);
//        System.out.println(printWriter.toString());

        File file = new File(FILE_PATH_PREFIX + File.separator + "Bean2.class");
        FileUtils.writeByteArrayToFile(file, buffer);

    }

Но файл класса результата не имеет ничего.

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package cn.curious.asm;

public class Bean {
}

Я чувствую растерянность по поводу ACC_SYNTHETI C, как его правильно использовать?


Обновление
Здесь вывод javap. -p заставляет его работать.

javap -v -l -s -p Bean.class 

Classfile /Users/Documents/work/idea_workspace/asmtest/src/main/java/cn/curious/asm/Bean.class
  Last modified 2020-3-5; size 127 bytes
  MD5 checksum 7367bcf65d9a32a72e4261101d3697cc
public class cn.curious.asm.Bean
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC
Constant pool:
  #1 = Utf8               cn/curious/asm/Bean
  #2 = Class              #1              // cn/curious/asm/Bean
  #3 = Utf8               java/lang/Object
  #4 = Class              #3              // java/lang/Object
  #5 = Utf8               lambda$main$1
  #6 = Utf8               ()V
  #7 = Utf8               Code
{
  private static void lambda$main$1();
    descriptor: ()V
    flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
    Code:
      stack=0, locals=0, args_size=0
         0: return
}

1 Ответ

1 голос
/ 05 марта 2020

Это идея синтетических c методов, это методы, сгенерированные компилятором, поэтому декомпиляторы часто пропускают его по умолчанию, так как по определению они не должны быть нужны в исходном коде.

Как и java спецификация гласит, что

Конструкция, испускаемая компилятором Java, должна быть помечена как syntheti c, если она не соответствует конструкции, объявленной явно или неявно в исходном коде, если только испускаемая конструкция не является методом инициализации класса (JVMS §2.9) .

И jvm one:

Флаг ACC_SYNTHETI C указывает, что этот метод был сгенерирован компилятором и не отображается в исходном коде [с некоторые исключения]

Попробуйте вместо этого использовать javap -verbose -private -s -classpath yourJar.jar my.Class (или просто непосредственно для подачи в класс), в нем должны быть перечислены все ваши методы. Или просто сгенерируйте второй нормальный метод, который вызовет этот метод syntheti c и проверит, можете ли вы его запустить. Или просто используйте отражения и метод getDeclaredMethods, чтобы получить все объявленные методы, включая синтетические c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...